move renderer ownership to engine (WIP)

This commit is contained in:
Attila Uygun 2023-05-25 07:43:09 +02:00
parent d5ee1c7313
commit 62033ab64d
16 changed files with 267 additions and 241 deletions

View File

@ -95,7 +95,7 @@ void Credits::Show() {
void Credits::Hide() { void Credits::Hide() {
text_animator_.SetEndCallback(Animator::kBlending, [&]() -> void { text_animator_.SetEndCallback(Animator::kBlending, [&]() -> void {
for (int i = 0; i < kNumLines; ++i) for (int i = 0; i < kNumLines; ++i)
text_[i].Destory(); text_[i].Destroy();
text_animator_.SetEndCallback(Animator::kBlending, nullptr); text_animator_.SetEndCallback(Animator::kBlending, nullptr);
text_animator_.SetVisible(false); text_animator_.SetVisible(false);
}); });

View File

@ -13,36 +13,53 @@
#include "engine/mesh.h" #include "engine/mesh.h"
#include "engine/platform/platform.h" #include "engine/platform/platform.h"
#include "engine/renderer/geometry.h" #include "engine/renderer/geometry.h"
#include "engine/renderer/opengl/renderer_opengl.h"
#include "engine/renderer/renderer.h" #include "engine/renderer/renderer.h"
#include "engine/renderer/shader.h" #include "engine/renderer/shader.h"
#include "engine/renderer/texture.h" #include "engine/renderer/texture.h"
#include "engine/renderer/vulkan/renderer_vulkan.h"
#include "engine/shader_source.h" #include "engine/shader_source.h"
#include "third_party/texture_compressor/texture_compressor.h" #include "third_party/texture_compressor/texture_compressor.h"
#define USE_VULKAN_RENDERER 1
using namespace base; using namespace base;
namespace eng { namespace eng {
Engine* Engine::singleton = nullptr; Engine* Engine::singleton = nullptr;
Engine::Engine(Platform* platform, Renderer* renderer) Engine::Engine(Platform* platform)
: platform_(platform), : platform_(platform),
renderer_(renderer), #if (USE_VULKAN_RENDERER == 1)
audio_mixer_{std::make_unique<AudioMixer>()} { renderer_{std::make_unique<RendererVulkan>()},
#else
renderer_{std::make_unique<RendererOpenGL>()},
#endif
audio_mixer_{std::make_unique<AudioMixer>()},
quad_{CreateRenderResource<Geometry>()},
pass_through_shader_{CreateRenderResource<Shader>()},
solid_shader_{CreateRenderResource<Shader>()} {
DCHECK(!singleton); DCHECK(!singleton);
singleton = this; singleton = this;
platform_->SetObserver(this);
renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this));
quad_ = CreateRenderResource<Geometry>();
pass_through_shader_ = CreateRenderResource<Shader>();
solid_shader_ = CreateRenderResource<Shader>();
stats_ = std::make_unique<ImageQuad>(); stats_ = std::make_unique<ImageQuad>();
} }
Engine::~Engine() { Engine::~Engine() {
LOG << "Shutting down engine.";
game_.reset();
stats_.reset(); stats_.reset();
textures_.clear();
shaders_.clear();
quad_.reset();
pass_through_shader_.reset();
solid_shader_.reset();
renderer_.reset();
singleton = nullptr; singleton = nullptr;
} }
@ -51,6 +68,8 @@ Engine& Engine::Get() {
} }
bool Engine::Initialize() { bool Engine::Initialize() {
InitializeRenderer();
// Normalize viewport. // Normalize viewport.
if (GetScreenWidth() > GetScreenHeight()) { if (GetScreenWidth() > GetScreenHeight()) {
float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight(); float aspect_ratio = (float)GetScreenWidth() / (float)GetScreenHeight();
@ -91,14 +110,6 @@ bool Engine::Initialize() {
return true; return true;
} }
void Engine::Shutdown() {
LOG << "Shutting down engine.";
game_.reset();
stats_->Destory();
textures_.clear();
shaders_.clear();
}
void Engine::Update(float delta_time) { void Engine::Update(float delta_time) {
seconds_accumulated_ += delta_time; seconds_accumulated_ += delta_time;
++tick_; ++tick_;
@ -137,20 +148,6 @@ void Engine::Draw(float frame_frac) {
renderer_->Present(); 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) { void Engine::AddDrawable(Drawable* drawable) {
DCHECK(std::find(drawables_.begin(), drawables_.end(), drawable) == DCHECK(std::find(drawables_.begin(), drawables_.end(), drawable) ==
drawables_.end()); drawables_.end());
@ -180,25 +177,25 @@ void Engine::RemoveAnimator(Animator* animator) {
} }
void Engine::SwitchRenderer(bool vulkan) { void Engine::SwitchRenderer(bool vulkan) {
Renderer* new_renderer = platform_->SwitchRenderer(vulkan); // Renderer* new_renderer = platform_->SwitchRenderer(vulkan);
if (new_renderer == renderer_) // if (new_renderer == renderer_)
return; // return;
renderer_ = new_renderer; // renderer_ = new_renderer;
renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); // renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this));
CreateTextureCompressors(); // CreateTextureCompressors();
for (auto& t : textures_) // for (auto& t : textures_)
t.second.texture->SetRenderer(renderer_); // t.second.texture->SetRenderer(renderer_);
for (auto& s : shaders_) // for (auto& s : shaders_)
s.second.shader->SetRenderer(renderer_); // s.second.shader->SetRenderer(renderer_);
quad_->SetRenderer(renderer_); // quad_->SetRenderer(renderer_);
pass_through_shader_->SetRenderer(renderer_); // pass_through_shader_->SetRenderer(renderer_);
solid_shader_->SetRenderer(renderer_); // solid_shader_->SetRenderer(renderer_);
ContextLost(); // ContextLost();
} }
void Engine::Exit() { void Engine::Exit() {
@ -323,40 +320,6 @@ void Engine::RemoveCustomShader(const std::string& asset_name) {
shaders_.erase(it); shaders_.erase(it);
} }
void Engine::AddInputEvent(std::unique_ptr<InputEvent> 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<InputEvent> Engine::GetNextInputEvent() { std::unique_ptr<InputEvent> Engine::GetNextInputEvent() {
std::unique_ptr<InputEvent> event; std::unique_ptr<InputEvent> event;
@ -490,6 +453,83 @@ bool Engine::IsMobile() const {
return platform_->mobile_device(); 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) {
audio_mixer_->Resume();
if (game_)
game_->GainedFocus(from_interstitial_ad);
}
void Engine::AddInputEvent(std::unique_ptr<InputEvent> 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));
}
void Engine::InitializeRenderer() {
bool res;
#if defined(__ANDROID__)
res = renderer_->Initialize(platform_->GetWindow());
#elif defined(__linux__)
res = renderer_->Initialize(platform_->GetDisplay(), platform_->GetWindow());
#endif
CHECK(res) << "Failed to initialize " << renderer_->GetDebugName()
<< " renderer.";
}
void Engine::CreateTextureCompressors() { void Engine::CreateTextureCompressors() {
tex_comp_alpha_.reset(); tex_comp_alpha_.reset();
tex_comp_opaque_.reset(); tex_comp_opaque_.reset();
@ -569,7 +609,7 @@ void Engine::SetSatsVisible(bool visible) {
if (visible) if (visible)
stats_->Create("stats_tex"); stats_->Create("stats_tex");
else else
stats_->Destory(); stats_->Destroy();
} }
std::unique_ptr<Image> Engine::PrintStats() { std::unique_ptr<Image> Engine::PrintStats() {

View File

@ -10,6 +10,7 @@
#include "base/random.h" #include "base/random.h"
#include "base/vecmath.h" #include "base/vecmath.h"
#include "engine/persistent_data.h" #include "engine/persistent_data.h"
#include "engine/platform/platform_observer.h"
class TextureCompressor; class TextureCompressor;
@ -29,25 +30,20 @@ class Shader;
class Texture; class Texture;
class Platform; class Platform;
class Engine { class Engine : public PlatformObserver {
public: public:
using CreateImageCB = std::function<std::unique_ptr<Image>()>; using CreateImageCB = std::function<std::unique_ptr<Image>()>;
Engine(Platform* platform, Renderer* renderer); Engine(Platform* platform);
~Engine(); ~Engine();
static Engine& Get(); static Engine& Get();
bool Initialize(); bool Initialize();
void Shutdown();
void Update(float delta_time); void Update(float delta_time);
void Draw(float frame_frac); void Draw(float frame_frac);
void LostFocus();
void GainedFocus(bool from_interstitial_ad);
void AddDrawable(Drawable* drawable); void AddDrawable(Drawable* drawable);
void RemoveDrawable(Drawable* drawable); void RemoveDrawable(Drawable* drawable);
@ -66,7 +62,7 @@ class Engine {
template <typename T> template <typename T>
std::unique_ptr<T> CreateRenderResource() { std::unique_ptr<T> CreateRenderResource() {
return std::unique_ptr<T>(static_cast<T*>(new T(renderer_))); return std::unique_ptr<T>(static_cast<T*>(new T(renderer_.get())));
} }
void SetImageSource(const std::string& asset_name, void SetImageSource(const std::string& asset_name,
@ -86,7 +82,6 @@ class Engine {
Shader* GetCustomShader(const std::string& asset_name); Shader* GetCustomShader(const std::string& asset_name);
void RemoveCustomShader(const std::string& asset_name); void RemoveCustomShader(const std::string& asset_name);
void AddInputEvent(std::unique_ptr<InputEvent> event);
std::unique_ptr<InputEvent> GetNextInputEvent(); std::unique_ptr<InputEvent> GetNextInputEvent();
void StartRecording(const Json::Value& payload); void StartRecording(const Json::Value& payload);
@ -174,10 +169,9 @@ class Engine {
static Engine* singleton; static Engine* singleton;
Platform* platform_ = nullptr; Platform* platform_ = nullptr;
Renderer* renderer_ = nullptr;
std::unique_ptr<Renderer> renderer_;
std::unique_ptr<AudioMixer> audio_mixer_; std::unique_ptr<AudioMixer> audio_mixer_;
std::unique_ptr<Game> game_; std::unique_ptr<Game> game_;
std::unique_ptr<Geometry> quad_; std::unique_ptr<Geometry> quad_;
@ -223,6 +217,16 @@ class Engine {
base::Randomf random_; base::Randomf random_;
// 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<InputEvent> event) final;
void InitializeRenderer();
void CreateTextureCompressors(); void CreateTextureCompressors();
void ContextLost(); void ContextLost();

View File

@ -13,7 +13,7 @@ namespace eng {
ImageQuad::ImageQuad() = default; ImageQuad::ImageQuad() = default;
ImageQuad::~ImageQuad() { ImageQuad::~ImageQuad() {
Destory(); Destroy();
} }
void ImageQuad::Create(const std::string& asset_name, void ImageQuad::Create(const std::string& asset_name,
@ -32,7 +32,8 @@ void ImageQuad::Create(const std::string& asset_name,
asset_name_ = asset_name; asset_name_ = asset_name;
} }
void ImageQuad::Destory() { // TODO: typo
void ImageQuad::Destroy() {
if (texture_) { if (texture_) {
Engine::Get().ReleaseTexture(asset_name_); Engine::Get().ReleaseTexture(asset_name_);
texture_ = nullptr; texture_ = nullptr;

View File

@ -24,7 +24,7 @@ class ImageQuad final : public Animatable {
int frame_width = 0, int frame_width = 0,
int frame_height = 0); int frame_height = 0);
void Destory(); void Destroy();
void AutoScale(); void AutoScale();

View File

@ -27,6 +27,8 @@ class InputEvent {
InputEvent(Type type, char key) : type_(type), key_(key) {} InputEvent(Type type, char key) : type_(type), key_(key) {}
~InputEvent() = default; ~InputEvent() = default;
void SetVector(base::Vector2f vec) { vec_ = vec; }
Type GetType() const { return type_; } Type GetType() const { return type_; }
size_t GetPointerId() const { return pointer_id_; } size_t GetPointerId() const { return pointer_id_; }

View File

@ -1,12 +1,10 @@
#include "engine/platform/platform.h" #include "engine/platform/platform.h"
#include <memory>
#include "base/log.h" #include "base/log.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "engine/engine.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; using namespace base;
@ -16,59 +14,46 @@ Platform::Platform() = default;
Platform::~Platform() = default; Platform::~Platform() = default;
Renderer* Platform::SwitchRenderer(bool vulkan) { // Renderer* Platform::SwitchRenderer(bool vulkan) {
DCHECK(renderer_); // DCHECK(renderer_);
if ((dynamic_cast<RendererVulkan*>(renderer_.get()) && vulkan) || // if ((dynamic_cast<RendererVulkan*>(renderer_.get()) && vulkan) ||
(dynamic_cast<RendererOpenGL*>(renderer_.get()) && !vulkan)) // (dynamic_cast<RendererOpenGL*>(renderer_.get()) && !vulkan))
return renderer_.get(); // return renderer_.get();
if (vulkan) // if (vulkan)
renderer_ = std::make_unique<RendererVulkan>(); // renderer_ = std::make_unique<RendererVulkan>();
else // else
renderer_ = std::make_unique<RendererOpenGL>(); // renderer_ = std::make_unique<RendererOpenGL>();
bool result = InitializeRenderer(); // bool result = InitializeRenderer();
CHECK(result) << "Failed to initialize " << renderer_->GetDebugName() // CHECK(result) << "Failed to initialize " << renderer_->GetDebugName()
<< " renderer."; // << " renderer.";
LOG << "Switched to " << renderer_->GetDebugName() << " renderer."; // LOG << "Switched to " << renderer_->GetDebugName() << " renderer.";
return renderer_.get(); // return renderer_.get();
} // }
void Platform::InitializeCommon() { void Platform::InitializeCommon() {
LOG << "Initializing platform."; LOG << "Initializing platform.";
thread_pool_.Initialize(); thread_pool_.Initialize();
TaskRunner::CreateThreadLocalTaskRunner(); TaskRunner::CreateThreadLocalTaskRunner();
#if (USE_VULKAN_RENDERER == 1)
renderer_ = std::make_unique<RendererVulkan>();
#else
renderer_ = std::make_unique<RendererOpenGL>();
#endif
}
void Platform::ShutdownCommon() {
LOG << "Shutting down platform.";
renderer_->Shutdown();
} }
void Platform::RunMainLoop() { void Platform::RunMainLoop() {
engine_ = std::unique_ptr<Engine> engine = std::make_unique<Engine>(this);
std::make_unique<Engine>(this, renderer_.get()); bool res = engine->Initialize();
bool res = engine_->Initialize();
CHECK(res) << "Failed to initialize the engine."; CHECK(res) << "Failed to initialize the engine.";
// Use fixed time steps. // Use fixed time steps.
float time_step = engine_->time_step(); float time_step = engine->time_step();
timer_.Reset(); timer_.Reset();
float accumulator = 0.0; float accumulator = 0.0;
float frame_frac = 0.0f; float frame_frac = 0.0f;
for (;;) { for (;;) {
engine_->Draw(frame_frac); engine->Draw(frame_frac);
// Accumulate time. // Accumulate time.
timer_.Update(); timer_.Update();
@ -79,12 +64,10 @@ void Platform::RunMainLoop() {
TaskRunner::GetThreadLocalTaskRunner()->SingleConsumerRun(); TaskRunner::GetThreadLocalTaskRunner()->SingleConsumerRun();
Update(); Update();
engine_->Update(time_step); engine->Update(time_step);
if (should_exit_) { if (should_exit_) {
thread_pool_.Shutdown(); thread_pool_.Shutdown();
engine_->Shutdown();
engine_.reset();
return; return;
} }
accumulator -= time_step; accumulator -= time_step;

View File

@ -1,7 +1,6 @@
#ifndef ENGINE_PLATFORM_PLATFORM_H #ifndef ENGINE_PLATFORM_PLATFORM_H
#define ENGINE_PLATFORM_PLATFORM_H #define ENGINE_PLATFORM_PLATFORM_H
#include <memory>
#include <string> #include <string>
#include "base/thread_pool.h" #include "base/thread_pool.h"
@ -24,8 +23,7 @@ struct ANativeWindow;
namespace eng { namespace eng {
class Renderer; class PlatformObserver;
class Engine;
class Platform { class Platform {
public: public:
@ -44,7 +42,9 @@ class Platform {
void Exit(); void Exit();
Renderer* SwitchRenderer(bool vulkan); void SetObserver(PlatformObserver* observer) { observer_ = observer; }
// Renderer* SwitchRenderer(bool vulkan);
void Vibrate(int duration); void Vibrate(int duration);
@ -66,7 +66,14 @@ class Platform {
bool mobile_device() const { return mobile_device_; } bool mobile_device() const { return mobile_device_; }
protected: #if defined(__ANDROID__)
ANativeWindow* GetWindow();
#elif defined(__linux__)
Display* GetDisplay();
Window GetWindow();
#endif
private:
base::Timer timer_; base::Timer timer_;
bool mobile_device_ = false; bool mobile_device_ = false;
@ -78,8 +85,7 @@ class Platform {
bool has_focus_ = false; bool has_focus_ = false;
bool should_exit_ = false; bool should_exit_ = false;
std::unique_ptr<Renderer> renderer_; PlatformObserver* observer_ = nullptr;
std::unique_ptr<Engine> engine_;
base::ThreadPool thread_pool_; base::ThreadPool thread_pool_;
@ -116,12 +122,11 @@ class Platform {
bool CreateWindow(int width, int height); bool CreateWindow(int width, int height);
void DestroyWindow(); void DestroyWindow();
XVisualInfo* GetXVisualInfo(Display* display);
#endif #endif
void InitializeCommon(); void InitializeCommon();
void ShutdownCommon();
bool InitializeRenderer();
Platform(const Platform&) = delete; Platform(const Platform&) = delete;
Platform& operator=(const Platform&) = delete; Platform& operator=(const Platform&) = delete;

View File

@ -1,5 +1,7 @@
#include "engine/platform/platform.h" #include "engine/platform/platform.h"
#include <memory>
#include <android_native_app_glue.h> #include <android_native_app_glue.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <jni.h> #include <jni.h>
@ -7,9 +9,8 @@
#include "base/log.h" #include "base/log.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "engine/engine.h"
#include "engine/input_event.h" #include "engine/input_event.h"
#include "engine/renderer/renderer.h" #include "engine/platform/platform_observer.h"
using namespace base; using namespace base;
@ -204,7 +205,7 @@ namespace eng {
int32_t Platform::HandleInput(android_app* app, AInputEvent* event) { int32_t Platform::HandleInput(android_app* app, AInputEvent* event) {
Platform* platform = reinterpret_cast<Platform*>(app->userData); Platform* platform = reinterpret_cast<Platform*>(app->userData);
if (!platform->engine_) if (!platform->observer_)
return 0; return 0;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY && if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_KEY &&
@ -212,7 +213,7 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) {
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) { if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_UP) {
auto input_event = auto input_event =
std::make_unique<InputEvent>(InputEvent::kNavigateBack); std::make_unique<InputEvent>(InputEvent::kNavigateBack);
platform->engine_->AddInputEvent(std::move(input_event)); platform->observer_->AddInputEvent(std::move(input_event));
} }
return 1; return 1;
} else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { } else if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
@ -227,7 +228,6 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) {
int32_t id = AMotionEvent_getPointerId(event, i); int32_t id = AMotionEvent_getPointerId(event, i);
if (id < 2) { if (id < 2) {
pos[id] = {AMotionEvent_getX(event, i), AMotionEvent_getY(event, i)}; pos[id] = {AMotionEvent_getX(event, i), AMotionEvent_getY(event, i)};
pos[id] = platform->engine_->ToPosition(pos[id]);
} }
} }
@ -239,34 +239,30 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) {
switch (flags) { switch (flags) {
case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_POINTER_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_pos_[pointer_id] = pos[pointer_id];
platform->pointer_down_[pointer_id] = true; platform->pointer_down_[pointer_id] = true;
input_event = input_event = std::make_unique<InputEvent>(InputEvent::kDragStart,
std::make_unique<InputEvent>(InputEvent::kDragStart, pointer_id, pointer_id, pos[pointer_id]);
pos[pointer_id] * Vector2f(1, -1));
break; break;
case AMOTION_EVENT_ACTION_UP: case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_POINTER_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_pos_[pointer_id] = pos[pointer_id];
platform->pointer_down_[pointer_id] = false; platform->pointer_down_[pointer_id] = false;
input_event = input_event = std::make_unique<InputEvent>(InputEvent::kDragEnd,
std::make_unique<InputEvent>(InputEvent::kDragEnd, pointer_id, pointer_id, pos[pointer_id]);
pos[pointer_id] * Vector2f(1, -1));
break; break;
case AMOTION_EVENT_ACTION_MOVE: case AMOTION_EVENT_ACTION_MOVE:
if (platform->pointer_down_[0] && pos[0] != platform->pointer_pos_[0]) { if (platform->pointer_down_[0] && pos[0] != platform->pointer_pos_[0]) {
platform->pointer_pos_[0] = pos[0]; platform->pointer_pos_[0] = pos[0];
input_event = std::make_unique<InputEvent>(InputEvent::kDrag, 0, input_event =
pos[0] * Vector2f(1, -1)); std::make_unique<InputEvent>(InputEvent::kDrag, 0, pos[0]);
} }
if (platform->pointer_down_[1] && pos[1] != platform->pointer_pos_[1]) { if (platform->pointer_down_[1] && pos[1] != platform->pointer_pos_[1]) {
platform->pointer_pos_[1] = pos[1]; platform->pointer_pos_[1] = pos[1];
input_event = std::make_unique<InputEvent>(InputEvent::kDrag, 1, input_event =
pos[1] * Vector2f(1, -1)); std::make_unique<InputEvent>(InputEvent::kDrag, 1, pos[1]);
} }
break; break;
@ -276,7 +272,7 @@ int32_t Platform::HandleInput(android_app* app, AInputEvent* event) {
} }
if (input_event) { if (input_event) {
platform->engine_->AddInputEvent(std::move(input_event)); platform->observer_->AddInputEvent(std::move(input_event));
return 1; return 1;
} }
} }
@ -295,30 +291,23 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) {
DLOG << "APP_CMD_INIT_WINDOW"; DLOG << "APP_CMD_INIT_WINDOW";
if (app->window != NULL) { if (app->window != NULL) {
platform->SetFrameRate(60); platform->SetFrameRate(60);
bool res = platform->InitializeRenderer(); if (platform->observer_)
CHECK(res) << "Failed to initialize " platform->observer_->OnWindowCreated();
<< platform->renderer_->GetDebugName() << " renderer.";
} }
break; break;
case APP_CMD_TERM_WINDOW: case APP_CMD_TERM_WINDOW:
DLOG << "APP_CMD_TERM_WINDOW"; DLOG << "APP_CMD_TERM_WINDOW";
platform->renderer_->Shutdown(); if (platform->observer_)
platform->observer_->OnWindowDestroyed();
break; break;
case APP_CMD_CONFIG_CHANGED: case APP_CMD_CONFIG_CHANGED:
DLOG << "APP_CMD_CONFIG_CHANGED"; DLOG << "APP_CMD_CONFIG_CHANGED";
if (platform->app_->window != NULL) { if (platform->app_->window != NULL && platform->observer_)
int width = platform->renderer_->screen_width(); platform->observer_->OnWindowResized(
int height = platform->renderer_->screen_height(); ANativeWindow_getWidth(app->window),
if (width != ANativeWindow_getWidth(app->window) || ANativeWindow_getHeight(app->window));
height != ANativeWindow_getHeight(app->window)) {
platform->renderer_->Shutdown();
bool res = platform->InitializeRenderer();
CHECK(res) << "Failed to initialize "
<< platform->renderer_->GetDebugName() << " renderer.";
}
}
break; break;
case APP_CMD_STOP: case APP_CMD_STOP:
@ -329,16 +318,16 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) {
DLOG << "APP_CMD_GAINED_FOCUS"; DLOG << "APP_CMD_GAINED_FOCUS";
platform->timer_.Reset(); platform->timer_.Reset();
platform->has_focus_ = true; platform->has_focus_ = true;
if (platform->engine_) if (platform->observer_)
platform->engine_->GainedFocus(g_showing_interstitial_ad); platform->observer_->GainedFocus(g_showing_interstitial_ad);
g_showing_interstitial_ad = false; g_showing_interstitial_ad = false;
break; break;
case APP_CMD_LOST_FOCUS: case APP_CMD_LOST_FOCUS:
DLOG << "APP_CMD_LOST_FOCUS"; DLOG << "APP_CMD_LOST_FOCUS";
platform->has_focus_ = false; platform->has_focus_ = false;
if (platform->engine_) if (platform->observer_)
platform->engine_->LostFocus(); platform->observer_->LostFocus();
break; break;
case APP_CMD_LOW_MEMORY: case APP_CMD_LOW_MEMORY:
@ -386,7 +375,7 @@ void Platform::Initialize(android_app* app) {
} }
void Platform::Shutdown() { void Platform::Shutdown() {
Platform::ShutdownCommon(); LOG << "Shutting down platform.";
} }
void Platform::Update() { void Platform::Update() {
@ -439,8 +428,8 @@ void Platform::SetFrameRate(float frame_rate) {
} }
} }
bool Platform::InitializeRenderer() { ANativeWindow* Platform::GetWindow() {
return renderer_->Initialize(app_->window); return app_->window;
} }
} // namespace eng } // namespace eng

View File

@ -1,11 +1,12 @@
#include "engine/platform/platform.h" #include "engine/platform/platform.h"
#include <memory>
#include "base/log.h" #include "base/log.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "base/vecmath.h" #include "base/vecmath.h"
#include "engine/engine.h"
#include "engine/input_event.h" #include "engine/input_event.h"
#include "engine/renderer/renderer.h" #include "engine/platform/platform_observer.h"
using namespace base; using namespace base;
@ -26,10 +27,6 @@ void Platform::Initialize() {
bool res = CreateWindow(800, 1205); bool res = CreateWindow(800, 1205);
CHECK(res) << "Failed to create window."; CHECK(res) << "Failed to create window.";
res = InitializeRenderer();
CHECK(res) << "Failed to initialize " << renderer_->GetDebugName()
<< " renderer.";
XSelectInput(display_, window_, XSelectInput(display_, window_,
KeyPressMask | Button1MotionMask | ButtonPressMask | KeyPressMask | Button1MotionMask | ButtonPressMask |
ButtonReleaseMask | FocusChangeMask); ButtonReleaseMask | FocusChangeMask);
@ -38,8 +35,7 @@ void Platform::Initialize() {
} }
void Platform::Shutdown() { void Platform::Shutdown() {
Platform::ShutdownCommon(); LOG << "Shutting down platform.";
DestroyWindow(); DestroyWindow();
} }
@ -52,47 +48,41 @@ void Platform::Update() {
KeySym key = XLookupKeysym(&e.xkey, 0); KeySym key = XLookupKeysym(&e.xkey, 0);
auto input_event = auto input_event =
std::make_unique<InputEvent>(InputEvent::kKeyPress, (char)key); std::make_unique<InputEvent>(InputEvent::kKeyPress, (char)key);
engine_->AddInputEvent(std::move(input_event)); observer_->AddInputEvent(std::move(input_event));
// TODO: e.xkey.state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)) // TODO: e.xkey.state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask))
break; break;
} }
case MotionNotify: { case MotionNotify: {
Vector2f v(e.xmotion.x, e.xmotion.y); Vector2f v(e.xmotion.x, e.xmotion.y);
v = engine_->ToPosition(v); auto input_event =
// DLOG << "drag: " << v; std::make_unique<InputEvent>(InputEvent::kDrag, 0, v);
auto input_event = std::make_unique<InputEvent>(InputEvent::kDrag, 0, observer_->AddInputEvent(std::move(input_event));
v * Vector2f(1, -1));
engine_->AddInputEvent(std::move(input_event));
break; break;
} }
case ButtonPress: { case ButtonPress: {
if (e.xbutton.button == 1) { if (e.xbutton.button == 1) {
Vector2f v(e.xbutton.x, e.xbutton.y); Vector2f v(e.xbutton.x, e.xbutton.y);
v = engine_->ToPosition(v); auto input_event =
// DLOG << "drag-start: " << v; std::make_unique<InputEvent>(InputEvent::kDragStart, 0, v);
auto input_event = std::make_unique<InputEvent>( observer_->AddInputEvent(std::move(input_event));
InputEvent::kDragStart, 0, v * Vector2f(1, -1));
engine_->AddInputEvent(std::move(input_event));
} }
break; break;
} }
case ButtonRelease: { case ButtonRelease: {
if (e.xbutton.button == 1) { if (e.xbutton.button == 1) {
Vector2f v(e.xbutton.x, e.xbutton.y); Vector2f v(e.xbutton.x, e.xbutton.y);
v = engine_->ToPosition(v); auto input_event =
// DLOG << "drag-end!"; std::make_unique<InputEvent>(InputEvent::kDragEnd, 0, v);
auto input_event = std::make_unique<InputEvent>( observer_->AddInputEvent(std::move(input_event));
InputEvent::kDragEnd, 0, v * Vector2f(1, -1));
engine_->AddInputEvent(std::move(input_event));
} }
break; break;
} }
case FocusOut: { case FocusOut: {
engine_->LostFocus(); observer_->LostFocus();
break; break;
} }
case FocusIn: { case FocusIn: {
engine_->GainedFocus(false); observer_->GainedFocus(false);
break; break;
} }
case ClientMessage: { case ClientMessage: {
@ -127,7 +117,7 @@ bool Platform::CreateWindow(int width, int height) {
Window root_window = DefaultRootWindow(display_); Window root_window = DefaultRootWindow(display_);
XVisualInfo* visual_info = renderer_->GetXVisualInfo(display_); XVisualInfo* visual_info = GetXVisualInfo(display_);
if (!visual_info) { if (!visual_info) {
LOG << "No appropriate visual found."; LOG << "No appropriate visual found.";
return false; return false;
@ -151,14 +141,29 @@ bool Platform::CreateWindow(int width, int height) {
void Platform::DestroyWindow() { void Platform::DestroyWindow() {
if (display_) { if (display_) {
XDestroyWindow(display_, window_); XDestroyWindow(display_, window_);
#if 0 // TODO: Figure out why XCloseDisplay is crashing
XCloseDisplay(display_); XCloseDisplay(display_);
#endif
display_ = nullptr; display_ = nullptr;
window_ = 0; window_ = 0;
} }
} }
bool Platform::InitializeRenderer() { Display* Platform::GetDisplay() {
return renderer_->Initialize(display_, window_); 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 } // namespace eng

View File

@ -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<InputEvent> event) = 0;
};
} // namespace eng
#endif // ENGINE_PLATFORM_PLATFORM_OBSERVER_H

View File

@ -89,10 +89,6 @@ class RendererOpenGL final : public Renderer {
const char* GetDebugName() final { return "OpenGL"; } const char* GetDebugName() final { return "OpenGL"; }
#if defined(__linux__) && !defined(__ANDROID__)
XVisualInfo* GetXVisualInfo(Display* display) final;
#endif
private: private:
struct GeometryOpenGL { struct GeometryOpenGL {
struct Element { struct Element {

View File

@ -21,9 +21,11 @@ bool RendererOpenGL::Initialize(Display* display, Window window) {
void RendererOpenGL::OnDestroy() {} void RendererOpenGL::OnDestroy() {}
bool RendererOpenGL::InitInternal() { 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_ = glx_context_ =
glXCreateContext(display_, GetXVisualInfo(display_), NULL, GL_TRUE); glXCreateContext(display_, visual_info, NULL, GL_TRUE);
if (!glx_context_) { if (!glx_context_) {
LOG << "Couldn't create the glx context."; LOG << "Couldn't create the glx context.";
return false; 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 } // namespace eng

View File

@ -94,10 +94,6 @@ class Renderer {
virtual const char* GetDebugName() = 0; virtual const char* GetDebugName() = 0;
#if defined(__linux__) && !defined(__ANDROID__)
virtual XVisualInfo* GetXVisualInfo(Display* display) = 0;
#endif
protected: protected:
struct TextureCompression { struct TextureCompression {
unsigned etc1 : 1; unsigned etc1 : 1;

View File

@ -74,10 +74,6 @@ class RendererVulkan final : public Renderer {
const char* GetDebugName() final { return "Vulkan"; } const char* GetDebugName() final { return "Vulkan"; }
#if defined(__linux__) && !defined(__ANDROID__)
XVisualInfo* GetXVisualInfo(Display* display) final;
#endif
private: private:
// VkBuffer or VkImage with allocator. // VkBuffer or VkImage with allocator.
template <typename T> template <typename T>

View File

@ -24,13 +24,4 @@ bool RendererVulkan::Initialize(Display* display, Window window) {
return InitializeInternal(); 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 } // namespace eng