diff --git a/build/android/app/CMakeLists.txt b/build/android/app/CMakeLists.txt index 129ee62..e10cd65 100644 --- a/build/android/app/CMakeLists.txt +++ b/build/android/app/CMakeLists.txt @@ -74,7 +74,6 @@ add_library(kaliber SHARED ../../../src/engine/platform/asset_file_android.cc ../../../src/engine/platform/asset_file.cc ../../../src/engine/platform/platform_android.cc - ../../../src/engine/platform/platform.cc ../../../src/engine/renderer/geometry.cc ../../../src/engine/renderer/opengl/render_command.cc ../../../src/engine/renderer/opengl/renderer_opengl_android.cc diff --git a/build/linux/Makefile b/build/linux/Makefile index 022be5a..8da112c 100644 --- a/build/linux/Makefile +++ b/build/linux/Makefile @@ -106,7 +106,6 @@ ENGINE_SRC := \ $(SRC_ROOT)/engine/persistent_data.cc \ $(SRC_ROOT)/engine/platform/asset_file_linux.cc \ $(SRC_ROOT)/engine/platform/asset_file.cc \ - $(SRC_ROOT)/engine/platform/platform.cc \ $(SRC_ROOT)/engine/platform/platform_linux.cc \ $(SRC_ROOT)/engine/renderer/geometry.cc \ $(SRC_ROOT)/engine/renderer/opengl/render_command.cc \ diff --git a/src/demo/credits.cc b/src/demo/credits.cc index 898903a..fe721ee 100644 --- a/src/demo/credits.cc +++ b/src/demo/credits.cc @@ -95,7 +95,7 @@ void Credits::Show() { void Credits::Hide() { text_animator_.SetEndCallback(Animator::kBlending, [&]() -> void { for (int i = 0; i < kNumLines; ++i) - text_[i].Destory(); + text_[i].Destroy(); text_animator_.SetEndCallback(Animator::kBlending, nullptr); text_animator_.SetVisible(false); }); diff --git a/src/engine/engine.cc b/src/engine/engine.cc index 7a6de43..f14cf21 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -1,6 +1,7 @@ #include "engine/engine.h" #include "base/log.h" +#include "base/task_runner.h" #include "engine/animator.h" #include "engine/audio/audio_mixer.h" #include "engine/drawable.h" @@ -13,36 +14,52 @@ #include "engine/mesh.h" #include "engine/platform/platform.h" #include "engine/renderer/geometry.h" +#include "engine/renderer/opengl/renderer_opengl.h" #include "engine/renderer/renderer.h" #include "engine/renderer/shader.h" #include "engine/renderer/texture.h" +#include "engine/renderer/vulkan/renderer_vulkan.h" #include "engine/shader_source.h" #include "third_party/texture_compressor/texture_compressor.h" +#define USE_VULKAN_RENDERER 1 + using namespace base; namespace eng { +extern void KaliberMain(Platform* platform) { + TaskRunner::CreateThreadLocalTaskRunner(); + Engine(platform).Run(); +} + Engine* Engine::singleton = nullptr; -Engine::Engine(Platform* platform, Renderer* renderer) +Engine::Engine(Platform* platform) : platform_(platform), - renderer_(renderer), - audio_mixer_{std::make_unique()} { + audio_mixer_{std::make_unique()}, + quad_{std::make_unique(nullptr)}, + pass_through_shader_{std::make_unique(nullptr)}, + solid_shader_{std::make_unique(nullptr)} { DCHECK(!singleton); singleton = this; - renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); - - quad_ = CreateRenderResource(); - pass_through_shader_ = CreateRenderResource(); - solid_shader_ = CreateRenderResource(); + platform_->SetObserver(this); stats_ = std::make_unique(); } Engine::~Engine() { + LOG << "Shutting down engine."; + + game_.reset(); stats_.reset(); + textures_.clear(); + shaders_.clear(); + quad_.reset(); + pass_through_shader_.reset(); + solid_shader_.reset(); + renderer_.reset(); singleton = nullptr; } @@ -50,7 +67,43 @@ Engine& Engine::Get() { return *singleton; } -bool Engine::Initialize() { +void Engine::Run() { + Initialize(); + + timer_.Reset(); + float accumulator = 0.0; + float frame_frac = 0.0f; + + for (;;) { + Draw(frame_frac); + + // Accumulate time. + timer_.Update(); + accumulator += timer_.GetSecondsPassed(); + + // Subdivide the frame time using fixed time steps. + while (accumulator >= time_step_) { + TaskRunner::GetThreadLocalTaskRunner()->SingleConsumerRun(); + + platform_->Update(); + Update(time_step_); + + if (platform_->should_exit()) { + return; + } + accumulator -= time_step_; + }; + + // Calculate frame fraction from remainder of the frame time. + frame_frac = accumulator / time_step_; + } +} + +void Engine::Initialize() { + thread_pool_.Initialize(); + + CreateRenderer(true); + // Normalize viewport. if (GetScreenWidth() > GetScreenHeight()) { float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight(); @@ -66,37 +119,16 @@ bool Engine::Initialize() { LOG << "image scale factor: " << GetImageScaleFactor(); - CreateTextureCompressors(); - system_font_ = std::make_unique(); system_font_->Load("engine/RobotoMono-Regular.ttf"); - if (!CreateRenderResources()) - return false; - SetImageSource("stats_tex", std::bind(&Engine::PrintStats, this)); stats_->SetZOrder(std::numeric_limits::max()); game_ = GameFactoryBase::CreateGame(""); - if (!game_) { - LOG << "No game found to run."; - return false; - } + CHECK(game_) << "No game found to run."; - if (!game_->Initialize()) { - LOG << "Failed to initialize the game."; - return false; - } - - return true; -} - -void Engine::Shutdown() { - LOG << "Shutting down engine."; - game_.reset(); - stats_->Destory(); - textures_.clear(); - shaders_.clear(); + CHECK(game_->Initialize()) << "Failed to initialize the game."; } void Engine::Update(float delta_time) { @@ -137,20 +169,6 @@ void Engine::Draw(float frame_frac) { renderer_->Present(); } -void Engine::LostFocus() { - audio_mixer_->Suspend(); - - if (game_) - game_->LostFocus(); -} - -void Engine::GainedFocus(bool from_interstitial_ad) { - audio_mixer_->Resume(); - - if (game_) - game_->GainedFocus(from_interstitial_ad); -} - void Engine::AddDrawable(Drawable* drawable) { DCHECK(std::find(drawables_.begin(), drawables_.end(), drawable) == drawables_.end()); @@ -179,25 +197,30 @@ void Engine::RemoveAnimator(Animator* animator) { } } -void Engine::SwitchRenderer(bool vulkan) { - Renderer* new_renderer = platform_->SwitchRenderer(vulkan); - if (new_renderer == renderer_) +void Engine::CreateRenderer(bool vulkan) { + if ((dynamic_cast(renderer_.get()) && vulkan) || + (dynamic_cast(renderer_.get()) && !vulkan)) return; - renderer_ = new_renderer; + if (vulkan) + renderer_ = std::make_unique(); + else + renderer_ = std::make_unique(); renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); + + bool result = InitializeRenderer(); + LOG_IF(!result) << "Failed to initialize " << renderer_->GetDebugName() + << " renderer."; + if (!result && vulkan) { + LOG << "Fallback to OpenGL renderer."; + renderer_ = std::make_unique(); + renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); + result = InitializeRenderer(); + } + CHECK(result) << "Failed to initialize " << renderer_->GetDebugName() + << " renderer."; + CreateTextureCompressors(); - - for (auto& t : textures_) - t.second.texture->SetRenderer(renderer_); - - for (auto& s : shaders_) - s.second.shader->SetRenderer(renderer_); - - quad_->SetRenderer(renderer_); - pass_through_shader_->SetRenderer(renderer_); - solid_shader_->SetRenderer(renderer_); - ContextLost(); } @@ -323,40 +346,6 @@ void Engine::RemoveCustomShader(const std::string& asset_name) { shaders_.erase(it); } -void Engine::AddInputEvent(std::unique_ptr event) { - if (replaying_) - return; - - switch (event->GetType()) { - case InputEvent::kDragEnd: - if (((GetScreenSize() / 2) * 0.9f - event->GetVector()).Length() <= - 0.25f) { - SetSatsVisible(!stats_->IsVisible()); - // TODO: Enqueue DragCancel so we can consume this event. - } - break; - case InputEvent::kKeyPress: - if (event->GetKeyPress() == 's') { - SetSatsVisible(!stats_->IsVisible()); - // Consume event. - return; - } - break; - case InputEvent::kDrag: - if (stats_->IsVisible()) { - if ((stats_->GetPosition() - event->GetVector()).Length() <= - stats_->GetSize().y) - stats_->SetPosition(event->GetVector()); - // TODO: Enqueue DragCancel so we can consume this event. - } - break; - default: - break; - } - - input_queue_.push_back(std::move(event)); -} - std::unique_ptr Engine::GetNextInputEvent() { std::unique_ptr event; @@ -490,6 +479,81 @@ bool Engine::IsMobile() const { return platform_->mobile_device(); } +void Engine::OnWindowCreated() { + InitializeRenderer(); +} + +void Engine::OnWindowDestroyed() { + renderer_->Shutdown(); +} + +void Engine::OnWindowResized(int width, int height) { + if (width != renderer_->screen_width() || + height != renderer_->screen_height()) { + renderer_->Shutdown(); + InitializeRenderer(); + } +} + +void Engine::LostFocus() { + audio_mixer_->Suspend(); + + if (game_) + game_->LostFocus(); +} + +void Engine::GainedFocus(bool from_interstitial_ad) { + timer_.Reset(); + audio_mixer_->Resume(); + + if (game_) + game_->GainedFocus(from_interstitial_ad); +} + +void Engine::AddInputEvent(std::unique_ptr event) { + if (replaying_) + return; + + event->SetVector(ToPosition(event->GetVector()) * Vector2f(1, -1)); + + switch (event->GetType()) { + case InputEvent::kDragEnd: + if (((GetScreenSize() / 2) * 0.9f - event->GetVector()).Length() <= + 0.25f) { + SetSatsVisible(!stats_->IsVisible()); + // TODO: Enqueue DragCancel so we can consume this event. + } + break; + case InputEvent::kKeyPress: + if (event->GetKeyPress() == 's') { + SetSatsVisible(!stats_->IsVisible()); + // Consume event. + return; + } + break; + case InputEvent::kDrag: + if (stats_->IsVisible()) { + if ((stats_->GetPosition() - event->GetVector()).Length() <= + stats_->GetSize().y) + stats_->SetPosition(event->GetVector()); + // TODO: Enqueue DragCancel so we can consume this event. + } + break; + default: + break; + } + + input_queue_.push_back(std::move(event)); +} + +bool Engine::InitializeRenderer() { +#if defined(__ANDROID__) + return renderer_->Initialize(platform_->GetWindow()); +#elif defined(__linux__) + return renderer_->Initialize(platform_->GetDisplay(), platform_->GetWindow()); +#endif +} + void Engine::CreateTextureCompressors() { tex_comp_alpha_.reset(); tex_comp_opaque_.reset(); @@ -513,24 +577,10 @@ void Engine::CreateTextureCompressors() { } void Engine::ContextLost() { - CreateRenderResources(); + quad_->SetRenderer(renderer_.get()); + pass_through_shader_->SetRenderer(renderer_.get()); + solid_shader_->SetRenderer(renderer_.get()); - for (auto& t : textures_) { - t.second.texture->Destroy(); - RefreshImage(t.first); - } - - for (auto& s : shaders_) { - auto source = std::make_unique(); - if (source->Load(s.second.file_name)) - s.second.shader->Create(std::move(source), quad_->vertex_description(), - quad_->primitive(), false); - } - - game_->ContextLost(); -} - -bool Engine::CreateRenderResources() { // This creates a normalized unit sized quad. static const char vertex_description[] = "p2f;t2f"; static const float vertices[] = { @@ -545,23 +595,37 @@ bool Engine::CreateRenderResources() { // Create the shader we can reuse for texture rendering. auto source = std::make_unique(); - if (!source->Load("engine/pass_through.glsl")) { + if (source->Load("engine/pass_through.glsl")) { + pass_through_shader_->Create(std::move(source), quad_->vertex_description(), + quad_->primitive(), false); + } else { LOG << "Could not create pass through shader."; - return false; } - pass_through_shader_->Create(std::move(source), quad_->vertex_description(), - quad_->primitive(), false); // Create the shader we can reuse for solid rendering. source = std::make_unique(); - if (!source->Load("engine/solid.glsl")) { + if (source->Load("engine/solid.glsl")) { + solid_shader_->Create(std::move(source), quad_->vertex_description(), + quad_->primitive(), false); + } else { LOG << "Could not create solid shader."; - return false; } - solid_shader_->Create(std::move(source), quad_->vertex_description(), - quad_->primitive(), false); - return true; + for (auto& t : textures_) { + t.second.texture->SetRenderer(renderer_.get()); + RefreshImage(t.first); + } + + for (auto& s : shaders_) { + s.second.shader->SetRenderer(renderer_.get()); + auto source = std::make_unique(); + if (source->Load(s.second.file_name)) + s.second.shader->Create(std::move(source), quad_->vertex_description(), + quad_->primitive(), false); + } + + if (game_) + game_->ContextLost(); } void Engine::SetSatsVisible(bool visible) { @@ -569,7 +633,7 @@ void Engine::SetSatsVisible(bool visible) { if (visible) stats_->Create("stats_tex"); else - stats_->Destory(); + stats_->Destroy(); } std::unique_ptr Engine::PrintStats() { diff --git a/src/engine/engine.h b/src/engine/engine.h index 5bf42a1..3f9ec7b 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -8,8 +8,11 @@ #include #include "base/random.h" +#include "base/thread_pool.h" +#include "base/timer.h" #include "base/vecmath.h" #include "engine/persistent_data.h" +#include "engine/platform/platform_observer.h" class TextureCompressor; @@ -29,24 +32,16 @@ class Shader; class Texture; class Platform; -class Engine { +class Engine : public PlatformObserver { public: using CreateImageCB = std::function()>; - Engine(Platform* platform, Renderer* renderer); + Engine(Platform* platform); ~Engine(); static Engine& Get(); - bool Initialize(); - - void Shutdown(); - - void Update(float delta_time); - void Draw(float frame_frac); - - void LostFocus(); - void GainedFocus(bool from_interstitial_ad); + void Run(); void AddDrawable(Drawable* drawable); void RemoveDrawable(Drawable* drawable); @@ -54,7 +49,7 @@ class Engine { void AddAnimator(Animator* animator); void RemoveAnimator(Animator* animator); - void SwitchRenderer(bool vulkan); + void CreateRenderer(bool vulkan); void Exit(); @@ -66,7 +61,7 @@ class Engine { template std::unique_ptr CreateRenderResource() { - return std::unique_ptr(static_cast(new T(renderer_))); + return std::unique_ptr(static_cast(new T(renderer_.get()))); } void SetImageSource(const std::string& asset_name, @@ -86,7 +81,6 @@ class Engine { Shader* GetCustomShader(const std::string& asset_name); void RemoveCustomShader(const std::string& asset_name); - void AddInputEvent(std::unique_ptr event); std::unique_ptr GetNextInputEvent(); void StartRecording(const Json::Value& payload); @@ -174,10 +168,9 @@ class Engine { static Engine* singleton; Platform* platform_ = nullptr; - Renderer* renderer_ = nullptr; + std::unique_ptr renderer_; std::unique_ptr audio_mixer_; - std::unique_ptr game_; std::unique_ptr quad_; @@ -221,14 +214,29 @@ class Engine { bool replaying_ = false; unsigned int replay_index_ = 0; + base::ThreadPool thread_pool_; + base::Timer timer_; base::Randomf random_; + void Initialize(); + + void Update(float delta_time); + void Draw(float frame_frac); + + // PlatformObserver implementation + void OnWindowCreated() final; + void OnWindowDestroyed() final; + void OnWindowResized(int width, int height) final; + void LostFocus() final; + void GainedFocus(bool from_interstitial_ad) final; + void AddInputEvent(std::unique_ptr event) final; + + bool InitializeRenderer(); + void CreateTextureCompressors(); void ContextLost(); - bool CreateRenderResources(); - void SetSatsVisible(bool visible); std::unique_ptr PrintStats(); diff --git a/src/engine/image_quad.cc b/src/engine/image_quad.cc index ab2e11a..dee7504 100644 --- a/src/engine/image_quad.cc +++ b/src/engine/image_quad.cc @@ -13,7 +13,7 @@ namespace eng { ImageQuad::ImageQuad() = default; ImageQuad::~ImageQuad() { - Destory(); + Destroy(); } void ImageQuad::Create(const std::string& asset_name, @@ -32,7 +32,8 @@ void ImageQuad::Create(const std::string& asset_name, asset_name_ = asset_name; } -void ImageQuad::Destory() { +// TODO: typo +void ImageQuad::Destroy() { if (texture_) { Engine::Get().ReleaseTexture(asset_name_); texture_ = nullptr; diff --git a/src/engine/image_quad.h b/src/engine/image_quad.h index d483774..c7e7629 100644 --- a/src/engine/image_quad.h +++ b/src/engine/image_quad.h @@ -24,7 +24,7 @@ class ImageQuad final : public Animatable { int frame_width = 0, int frame_height = 0); - void Destory(); + void Destroy(); void AutoScale(); diff --git a/src/engine/input_event.h b/src/engine/input_event.h index e99fa33..e37d808 100644 --- a/src/engine/input_event.h +++ b/src/engine/input_event.h @@ -27,6 +27,8 @@ class InputEvent { InputEvent(Type type, char key) : type_(type), key_(key) {} ~InputEvent() = default; + void SetVector(base::Vector2f vec) { vec_ = vec; } + Type GetType() const { return type_; } size_t GetPointerId() const { return pointer_id_; } diff --git a/src/engine/platform/platform.cc b/src/engine/platform/platform.cc deleted file mode 100644 index c65d6ea..0000000 --- a/src/engine/platform/platform.cc +++ /dev/null @@ -1,98 +0,0 @@ -#include "engine/platform/platform.h" - -#include "base/log.h" -#include "base/task_runner.h" -#include "engine/engine.h" -#include "engine/renderer/opengl/renderer_opengl.h" -#include "engine/renderer/vulkan/renderer_vulkan.h" - -#define USE_VULKAN_RENDERER 1 - -using namespace base; - -namespace eng { - -Platform::Platform() = default; - -Platform::~Platform() = default; - -Renderer* Platform::SwitchRenderer(bool vulkan) { - DCHECK(renderer_); - - if ((dynamic_cast(renderer_.get()) && vulkan) || - (dynamic_cast(renderer_.get()) && !vulkan)) - return renderer_.get(); - - if (vulkan) - renderer_ = std::make_unique(); - else - renderer_ = std::make_unique(); - - bool result = InitializeRenderer(); - CHECK(result) << "Failed to initialize " << renderer_->GetDebugName() - << " renderer."; - LOG << "Switched to " << renderer_->GetDebugName() << " renderer."; - return renderer_.get(); -} - -void Platform::InitializeCommon() { - LOG << "Initializing platform."; - - thread_pool_.Initialize(); - TaskRunner::CreateThreadLocalTaskRunner(); - -#if (USE_VULKAN_RENDERER == 1) - renderer_ = std::make_unique(); -#else - renderer_ = std::make_unique(); -#endif -} - -void Platform::ShutdownCommon() { - LOG << "Shutting down platform."; - - renderer_->Shutdown(); -} - -void Platform::RunMainLoop() { - engine_ = - std::make_unique(this, renderer_.get()); - bool res = engine_->Initialize(); - CHECK(res) << "Failed to initialize the engine."; - - // Use fixed time steps. - float time_step = engine_->time_step(); - - timer_.Reset(); - float accumulator = 0.0; - float frame_frac = 0.0f; - - for (;;) { - engine_->Draw(frame_frac); - - // Accumulate time. - timer_.Update(); - accumulator += timer_.GetSecondsPassed(); - - // Subdivide the frame time. - while (accumulator >= time_step) { - TaskRunner::GetThreadLocalTaskRunner()->SingleConsumerRun(); - - Update(); - engine_->Update(time_step); - - if (should_exit_) { - thread_pool_.Shutdown(); - engine_->Shutdown(); - engine_.reset(); - return; - } - accumulator -= time_step; - }; - - // Calculate frame fraction from remainder of the frame time. - frame_frac = accumulator / time_step; - } -} - -} // namespace eng diff --git a/src/engine/platform/platform.h b/src/engine/platform/platform.h index 977a868..37e1805 100644 --- a/src/engine/platform/platform.h +++ b/src/engine/platform/platform.h @@ -1,12 +1,8 @@ #ifndef ENGINE_PLATFORM_PLATFORM_H #define ENGINE_PLATFORM_PLATFORM_H -#include #include -#include "base/thread_pool.h" -#include "base/timer.h" - #if defined(__ANDROID__) #include "../../base/vecmath.h" @@ -24,27 +20,22 @@ struct ANativeWindow; namespace eng { -class Renderer; -class Engine; +class PlatformObserver; class Platform { public: - Platform(); - ~Platform(); - #if defined(__ANDROID__) - void Initialize(android_app* app); + Platform(android_app* app); #elif defined(__linux__) - void Initialize(); + Platform(); #endif - - void Shutdown(); + ~Platform(); void Update(); void Exit(); - Renderer* SwitchRenderer(bool vulkan); + void SetObserver(PlatformObserver* observer) { observer_ = observer; } void Vibrate(int duration); @@ -54,8 +45,6 @@ class Platform { void SetKeepScreenOn(bool keep_screen_on); - void RunMainLoop(); - int GetDeviceDpi() const { return device_dpi_; } const std::string& GetRootPath() const { return root_path_; } @@ -66,9 +55,16 @@ class Platform { bool mobile_device() const { return mobile_device_; } - protected: - base::Timer timer_; + bool should_exit() const { return should_exit_; } +#if defined(__ANDROID__) + ANativeWindow* GetWindow(); +#elif defined(__linux__) + Display* GetDisplay(); + Window GetWindow(); +#endif + + private: bool mobile_device_ = false; int device_dpi_ = 100; std::string root_path_; @@ -78,10 +74,7 @@ class Platform { bool has_focus_ = false; bool should_exit_ = false; - std::unique_ptr renderer_; - std::unique_ptr engine_; - - base::ThreadPool thread_pool_; + PlatformObserver* observer_ = nullptr; #if defined(__ANDROID__) @@ -116,13 +109,10 @@ class Platform { bool CreateWindow(int width, int height); void DestroyWindow(); + XVisualInfo* GetXVisualInfo(Display* display); + #endif - void InitializeCommon(); - void ShutdownCommon(); - - bool InitializeRenderer(); - Platform(const Platform&) = delete; Platform& operator=(const Platform&) = delete; }; diff --git a/src/engine/platform/platform_android.cc b/src/engine/platform/platform_android.cc index 1bf6c13..8adf003 100644 --- a/src/engine/platform/platform_android.cc +++ b/src/engine/platform/platform_android.cc @@ -1,15 +1,15 @@ #include "engine/platform/platform.h" +#include + #include #include #include #include #include "base/log.h" -#include "base/task_runner.h" -#include "engine/engine.h" #include "engine/input_event.h" -#include "engine/renderer/renderer.h" +#include "engine/platform/platform_observer.h" using namespace base; @@ -201,10 +201,12 @@ int32_t GetDensityDpi(android_app* app) { namespace eng { +void KaliberMain(Platform* platform); + int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { Platform* platform = reinterpret_cast(app->userData); - if (!platform->engine_) + if (!platform->observer_) return 0; if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY && @@ -212,7 +214,7 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) { auto input_event = std::make_unique(InputEvent::kNavigateBack); - platform->engine_->AddInputEvent(std::move(input_event)); + platform->observer_->AddInputEvent(std::move(input_event)); } return 1; } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { @@ -227,7 +229,6 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { int32_t id = AMotionEvent_getPointerId(event, i); if (id < 2) { pos[id] = {AMotionEvent_getX(event, i), AMotionEvent_getY(event, i)}; - pos[id] = platform->engine_->ToPosition(pos[id]); } } @@ -239,34 +240,30 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { switch (flags) { case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_POINTER_DOWN: - // DLOG << "AMOTION_EVENT_ACTION_DOWN - pointer_id: " << pointer_id; platform->pointer_pos_[pointer_id] = pos[pointer_id]; platform->pointer_down_[pointer_id] = true; - input_event = - std::make_unique(InputEvent::kDragStart, pointer_id, - pos[pointer_id] * Vector2f(1, -1)); + input_event = std::make_unique(InputEvent::kDragStart, + pointer_id, pos[pointer_id]); break; case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_POINTER_UP: - // DLOG << "AMOTION_EVENT_ACTION_UP - pointer_id: " << pointer_id; platform->pointer_pos_[pointer_id] = pos[pointer_id]; platform->pointer_down_[pointer_id] = false; - input_event = - std::make_unique(InputEvent::kDragEnd, pointer_id, - pos[pointer_id] * Vector2f(1, -1)); + input_event = std::make_unique(InputEvent::kDragEnd, + pointer_id, pos[pointer_id]); break; case AMOTION_EVENT_ACTION_MOVE: if (platform->pointer_down_[0] && pos[0] != platform->pointer_pos_[0]) { platform->pointer_pos_[0] = pos[0]; - input_event = std::make_unique(InputEvent::kDrag, 0, - pos[0] * Vector2f(1, -1)); + input_event = + std::make_unique(InputEvent::kDrag, 0, pos[0]); } if (platform->pointer_down_[1] && pos[1] != platform->pointer_pos_[1]) { platform->pointer_pos_[1] = pos[1]; - input_event = std::make_unique(InputEvent::kDrag, 1, - pos[1] * Vector2f(1, -1)); + input_event = + std::make_unique(InputEvent::kDrag, 1, pos[1]); } break; @@ -276,7 +273,7 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { } if (input_event) { - platform->engine_->AddInputEvent(std::move(input_event)); + platform->observer_->AddInputEvent(std::move(input_event)); return 1; } } @@ -295,30 +292,23 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) { DLOG << "APP_CMD_INIT_WINDOW"; if (app->window != NULL) { platform->SetFrameRate(60); - bool res = platform->InitializeRenderer(); - CHECK(res) << "Failed to initialize " - << platform->renderer_->GetDebugName() << " renderer."; + if (platform->observer_) + platform->observer_->OnWindowCreated(); } break; case APP_CMD_TERM_WINDOW: DLOG << "APP_CMD_TERM_WINDOW"; - platform->renderer_->Shutdown(); + if (platform->observer_) + platform->observer_->OnWindowDestroyed(); break; case APP_CMD_CONFIG_CHANGED: DLOG << "APP_CMD_CONFIG_CHANGED"; - if (platform->app_->window != NULL) { - int width = platform->renderer_->screen_width(); - int height = platform->renderer_->screen_height(); - if (width != ANativeWindow_getWidth(app->window) || - height != ANativeWindow_getHeight(app->window)) { - platform->renderer_->Shutdown(); - bool res = platform->InitializeRenderer(); - CHECK(res) << "Failed to initialize " - << platform->renderer_->GetDebugName() << " renderer."; - } - } + if (platform->app_->window != NULL && platform->observer_) + platform->observer_->OnWindowResized( + ANativeWindow_getWidth(app->window), + ANativeWindow_getHeight(app->window)); break; case APP_CMD_STOP: @@ -327,18 +317,18 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) { case APP_CMD_GAINED_FOCUS: DLOG << "APP_CMD_GAINED_FOCUS"; - platform->timer_.Reset(); + // platform->timer_.Reset(); platform->has_focus_ = true; - if (platform->engine_) - platform->engine_->GainedFocus(g_showing_interstitial_ad); + if (platform->observer_) + platform->observer_->GainedFocus(g_showing_interstitial_ad); g_showing_interstitial_ad = false; break; case APP_CMD_LOST_FOCUS: DLOG << "APP_CMD_LOST_FOCUS"; platform->has_focus_ = false; - if (platform->engine_) - platform->engine_->LostFocus(); + if (platform->observer_) + platform->observer_->LostFocus(); break; case APP_CMD_LOW_MEMORY: @@ -347,11 +337,8 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) { } } -void Platform::Initialize(android_app* app) { - Platform::InitializeCommon(); - +Platform::Platform(android_app* app) { app_ = app; - mobile_device_ = true; root_path_ = ::GetApkPath(app->activity); @@ -385,8 +372,8 @@ void Platform::Initialize(android_app* app) { Update(); } -void Platform::Shutdown() { - Platform::ShutdownCommon(); +Platform::~Platform() { + LOG << "Shutting down platform."; } void Platform::Update() { @@ -439,16 +426,14 @@ void Platform::SetFrameRate(float frame_rate) { } } -bool Platform::InitializeRenderer() { - return renderer_->Initialize(app_->window); +ANativeWindow* Platform::GetWindow() { + return app_->window; } } // namespace eng void android_main(android_app* app) { - eng::Platform platform; - platform.Initialize(app); - platform.RunMainLoop(); - platform.Shutdown(); + eng::Platform platform(app); + eng::KaliberMain(&platform); _exit(0); } diff --git a/src/engine/platform/platform_linux.cc b/src/engine/platform/platform_linux.cc index 4d0982d..30b83d8 100644 --- a/src/engine/platform/platform_linux.cc +++ b/src/engine/platform/platform_linux.cc @@ -1,19 +1,19 @@ #include "engine/platform/platform.h" +#include + #include "base/log.h" -#include "base/task_runner.h" #include "base/vecmath.h" -#include "engine/engine.h" #include "engine/input_event.h" -#include "engine/renderer/renderer.h" +#include "engine/platform/platform_observer.h" using namespace base; namespace eng { -void Platform::Initialize() { - Platform::InitializeCommon(); +void KaliberMain(Platform* platform); +Platform::Platform() { root_path_ = "../../"; LOG << "Root path: " << root_path_.c_str(); @@ -26,10 +26,6 @@ void Platform::Initialize() { bool res = CreateWindow(800, 1205); CHECK(res) << "Failed to create window."; - res = InitializeRenderer(); - CHECK(res) << "Failed to initialize " << renderer_->GetDebugName() - << " renderer."; - XSelectInput(display_, window_, KeyPressMask | Button1MotionMask | ButtonPressMask | ButtonReleaseMask | FocusChangeMask); @@ -37,9 +33,8 @@ void Platform::Initialize() { XSetWMProtocols(display_, window_, &WM_DELETE_WINDOW, 1); } -void Platform::Shutdown() { - Platform::ShutdownCommon(); - +Platform::~Platform() { + LOG << "Shutting down platform."; DestroyWindow(); } @@ -52,47 +47,41 @@ void Platform::Update() { KeySym key = XLookupKeysym(&e.xkey, 0); auto input_event = std::make_unique(InputEvent::kKeyPress, (char)key); - engine_->AddInputEvent(std::move(input_event)); + observer_->AddInputEvent(std::move(input_event)); // TODO: e.xkey.state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)) break; } case MotionNotify: { Vector2f v(e.xmotion.x, e.xmotion.y); - v = engine_->ToPosition(v); - // DLOG << "drag: " << v; - auto input_event = std::make_unique(InputEvent::kDrag, 0, - v * Vector2f(1, -1)); - engine_->AddInputEvent(std::move(input_event)); + auto input_event = + std::make_unique(InputEvent::kDrag, 0, v); + observer_->AddInputEvent(std::move(input_event)); break; } case ButtonPress: { if (e.xbutton.button == 1) { Vector2f v(e.xbutton.x, e.xbutton.y); - v = engine_->ToPosition(v); - // DLOG << "drag-start: " << v; - auto input_event = std::make_unique( - InputEvent::kDragStart, 0, v * Vector2f(1, -1)); - engine_->AddInputEvent(std::move(input_event)); + auto input_event = + std::make_unique(InputEvent::kDragStart, 0, v); + observer_->AddInputEvent(std::move(input_event)); } break; } case ButtonRelease: { if (e.xbutton.button == 1) { Vector2f v(e.xbutton.x, e.xbutton.y); - v = engine_->ToPosition(v); - // DLOG << "drag-end!"; - auto input_event = std::make_unique( - InputEvent::kDragEnd, 0, v * Vector2f(1, -1)); - engine_->AddInputEvent(std::move(input_event)); + auto input_event = + std::make_unique(InputEvent::kDragEnd, 0, v); + observer_->AddInputEvent(std::move(input_event)); } break; } case FocusOut: { - engine_->LostFocus(); + observer_->LostFocus(); break; } case FocusIn: { - engine_->GainedFocus(false); + observer_->GainedFocus(false); break; } case ClientMessage: { @@ -127,7 +116,7 @@ bool Platform::CreateWindow(int width, int height) { Window root_window = DefaultRootWindow(display_); - XVisualInfo* visual_info = renderer_->GetXVisualInfo(display_); + XVisualInfo* visual_info = GetXVisualInfo(display_); if (!visual_info) { LOG << "No appropriate visual found."; return false; @@ -151,22 +140,35 @@ bool Platform::CreateWindow(int width, int height) { void Platform::DestroyWindow() { if (display_) { XDestroyWindow(display_, window_); +#if 0 // TODO: Figure out why XCloseDisplay is crashing XCloseDisplay(display_); +#endif display_ = nullptr; window_ = 0; } } -bool Platform::InitializeRenderer() { - return renderer_->Initialize(display_, window_); +Display* Platform::GetDisplay() { + return display_; +} + +Window Platform::GetWindow() { + return window_; +} + +XVisualInfo* Platform::GetXVisualInfo(Display* display) { + long visual_mask = VisualScreenMask; + int num_visuals; + XVisualInfo visual_info_template = {}; + visual_info_template.screen = DefaultScreen(display); + return XGetVisualInfo(display, visual_mask, &visual_info_template, + &num_visuals); } } // namespace eng int main(int argc, char** argv) { eng::Platform platform; - platform.Initialize(); - platform.RunMainLoop(); - platform.Shutdown(); + eng::KaliberMain(&platform); return 0; } diff --git a/src/engine/platform/platform_observer.h b/src/engine/platform/platform_observer.h new file mode 100644 index 0000000..d6c11a8 --- /dev/null +++ b/src/engine/platform/platform_observer.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_PLATFORM_PLATFORM_OBSERVER_H +#define ENGINE_PLATFORM_PLATFORM_OBSERVER_H + +namespace eng { + +class InputEvent; + +class PlatformObserver { + public: + PlatformObserver() = default; + virtual ~PlatformObserver() = default; + + virtual void OnWindowCreated() = 0; + virtual void OnWindowDestroyed() = 0; + virtual void OnWindowResized(int width, int height) = 0; + virtual void LostFocus() = 0; + virtual void GainedFocus(bool from_interstitial_ad) = 0; + virtual void AddInputEvent(std::unique_ptr event) = 0; +}; + +} // namespace eng + +#endif // ENGINE_PLATFORM_PLATFORM_OBSERVER_H diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index 75f983a..aa7c9f4 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -89,10 +89,6 @@ class RendererOpenGL final : public Renderer { const char* GetDebugName() final { return "OpenGL"; } -#if defined(__linux__) && !defined(__ANDROID__) - XVisualInfo* GetXVisualInfo(Display* display) final; -#endif - private: struct GeometryOpenGL { struct Element { diff --git a/src/engine/renderer/opengl/renderer_opengl_linux.cc b/src/engine/renderer/opengl/renderer_opengl_linux.cc index 5bb452a..267a5bf 100644 --- a/src/engine/renderer/opengl/renderer_opengl_linux.cc +++ b/src/engine/renderer/opengl/renderer_opengl_linux.cc @@ -21,9 +21,11 @@ bool RendererOpenGL::Initialize(Display* display, Window window) { void RendererOpenGL::OnDestroy() {} bool RendererOpenGL::InitInternal() { - // Create the OpenGL context. + GLint glx_attributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, + None}; + XVisualInfo* visual_info = glXChooseVisual(display_, 0, glx_attributes); glx_context_ = - glXCreateContext(display_, GetXVisualInfo(display_), NULL, GL_TRUE); + glXCreateContext(display_, visual_info, NULL, GL_TRUE); if (!glx_context_) { LOG << "Couldn't create the glx context."; return false; @@ -59,11 +61,4 @@ void RendererOpenGL::HandleCmdPresent(RenderCommand* cmd) { } } -XVisualInfo* RendererOpenGL::GetXVisualInfo(Display* display) { - // Look for the right visual to set up the OpenGL context. - GLint glx_attributes[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, - None}; - return glXChooseVisual(display, 0, glx_attributes); -} - } // namespace eng diff --git a/src/engine/renderer/renderer.h b/src/engine/renderer/renderer.h index e6bed68..2ce496b 100644 --- a/src/engine/renderer/renderer.h +++ b/src/engine/renderer/renderer.h @@ -94,10 +94,6 @@ class Renderer { virtual const char* GetDebugName() = 0; -#if defined(__linux__) && !defined(__ANDROID__) - virtual XVisualInfo* GetXVisualInfo(Display* display) = 0; -#endif - protected: struct TextureCompression { unsigned etc1 : 1; diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index 38b9bee..5e54c98 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -74,10 +74,6 @@ class RendererVulkan final : public Renderer { const char* GetDebugName() final { return "Vulkan"; } -#if defined(__linux__) && !defined(__ANDROID__) - XVisualInfo* GetXVisualInfo(Display* display) final; -#endif - private: // VkBuffer or VkImage with allocator. template diff --git a/src/engine/renderer/vulkan/renderer_vulkan_linux.cc b/src/engine/renderer/vulkan/renderer_vulkan_linux.cc index 4cb66bd..35eea3d 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan_linux.cc +++ b/src/engine/renderer/vulkan/renderer_vulkan_linux.cc @@ -24,13 +24,4 @@ bool RendererVulkan::Initialize(Display* display, Window window) { return InitializeInternal(); } -XVisualInfo* RendererVulkan::GetXVisualInfo(Display* display) { - long visual_mask = VisualScreenMask; - int num_visuals; - XVisualInfo visual_info_template = {}; - visual_info_template.screen = DefaultScreen(display); - return XGetVisualInfo(display, visual_mask, &visual_info_template, - &num_visuals); -} - } // namespace eng