diff --git a/src/engine/engine.cc b/src/engine/engine.cc index 270c1fc..e323d57 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -71,22 +71,7 @@ bool Engine::Initialize() { LOG << "image scale factor: " << GetImageScaleFactor(); - if (renderer_->SupportsDXT5()) { - tex_comp_alpha_ = TextureCompressor::Create(TextureCompressor::kFormatDXT5); - } else if (renderer_->SupportsATC()) { - tex_comp_alpha_ = - TextureCompressor::Create(TextureCompressor::kFormatATCIA); - } - - if (renderer_->SupportsDXT1()) { - tex_comp_opaque_ = - TextureCompressor::Create(TextureCompressor::kFormatDXT1); - } else if (renderer_->SupportsATC()) { - tex_comp_opaque_ = TextureCompressor::Create(TextureCompressor::kFormatATC); - } else if (renderer_->SupportsETC1()) { - tex_comp_opaque_ = - TextureCompressor::Create(TextureCompressor::kFormatETC1); - } + CreateTextureCompressors(); system_font_ = std::make_unique(); system_font_->Load("engine/RobotoMono-Regular.ttf"); @@ -199,6 +184,28 @@ void Engine::RemoveAnimator(Animator* animator) { } } +void Engine::SwitchRenderer(bool vulkan) { + Renderer* new_renderer = platform_->SwitchRenderer(vulkan); + if (new_renderer == renderer_) + return; + + renderer_ = new_renderer; + renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this)); + 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(); +} + void Engine::Exit() { platform_->Exit(); } @@ -488,6 +495,28 @@ bool Engine::IsMobile() const { return platform_->mobile_device(); } +void Engine::CreateTextureCompressors() { + tex_comp_alpha_.reset(); + tex_comp_opaque_.reset(); + + if (renderer_->SupportsDXT5()) { + tex_comp_alpha_ = TextureCompressor::Create(TextureCompressor::kFormatDXT5); + } else if (renderer_->SupportsATC()) { + tex_comp_alpha_ = + TextureCompressor::Create(TextureCompressor::kFormatATCIA); + } + + if (renderer_->SupportsDXT1()) { + tex_comp_opaque_ = + TextureCompressor::Create(TextureCompressor::kFormatDXT1); + } else if (renderer_->SupportsATC()) { + tex_comp_opaque_ = TextureCompressor::Create(TextureCompressor::kFormatATC); + } else if (renderer_->SupportsETC1()) { + tex_comp_opaque_ = + TextureCompressor::Create(TextureCompressor::kFormatETC1); + } +} + void Engine::ContextLost() { CreateRenderResources(); diff --git a/src/engine/engine.h b/src/engine/engine.h index fbd7cda..c47f9c7 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -55,6 +55,8 @@ class Engine { void AddAnimator(Animator* animator); void RemoveAnimator(Animator* animator); + void SwitchRenderer(bool vulkan); + void Exit(); // Convert size from pixels to viewport scale. @@ -222,6 +224,8 @@ class Engine { base::Randomf random_; + void CreateTextureCompressors(); + void ContextLost(); bool CreateRenderResources(); diff --git a/src/engine/platform/platform.cc b/src/engine/platform/platform.cc index 3f7f0e6..96bc5b6 100644 --- a/src/engine/platform/platform.cc +++ b/src/engine/platform/platform.cc @@ -22,6 +22,25 @@ 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."; diff --git a/src/engine/platform/platform.h b/src/engine/platform/platform.h index d65169f..a5ef7ac 100644 --- a/src/engine/platform/platform.h +++ b/src/engine/platform/platform.h @@ -45,6 +45,8 @@ class Platform { void Exit(); + Renderer* SwitchRenderer(bool vulkan); + void Vibrate(int duration); void ShowInterstitialAd(); @@ -121,6 +123,8 @@ class Platform { 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 ff9a551..1bf6c13 100644 --- a/src/engine/platform/platform_android.cc +++ b/src/engine/platform/platform_android.cc @@ -295,7 +295,7 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) { DLOG << "APP_CMD_INIT_WINDOW"; if (app->window != NULL) { platform->SetFrameRate(60); - bool res = platform->renderer_->Initialize(app->window); + bool res = platform->InitializeRenderer(); CHECK(res) << "Failed to initialize " << platform->renderer_->GetDebugName() << " renderer."; } @@ -314,7 +314,7 @@ void Platform::HandleCmd(android_app* app, int32_t cmd) { if (width != ANativeWindow_getWidth(app->window) || height != ANativeWindow_getHeight(app->window)) { platform->renderer_->Shutdown(); - bool res = platform->renderer_->Initialize(platform->app_->window); + bool res = platform->InitializeRenderer(); CHECK(res) << "Failed to initialize " << platform->renderer_->GetDebugName() << " renderer."; } @@ -439,6 +439,10 @@ void Platform::SetFrameRate(float frame_rate) { } } +bool Platform::InitializeRenderer() { + return renderer_->Initialize(app_->window); +} + } // namespace eng void android_main(android_app* app) { diff --git a/src/engine/platform/platform_linux.cc b/src/engine/platform/platform_linux.cc index b3fc648..4d0982d 100644 --- a/src/engine/platform/platform_linux.cc +++ b/src/engine/platform/platform_linux.cc @@ -26,7 +26,7 @@ void Platform::Initialize() { bool res = CreateWindow(800, 1205); CHECK(res) << "Failed to create window."; - res = renderer_->Initialize(display_, window_); + res = InitializeRenderer(); CHECK(res) << "Failed to initialize " << renderer_->GetDebugName() << " renderer."; @@ -157,6 +157,10 @@ void Platform::DestroyWindow() { } } +bool Platform::InitializeRenderer() { + return renderer_->Initialize(display_, window_); +} + } // namespace eng int main(int argc, char** argv) { diff --git a/src/engine/renderer/opengl/renderer_opengl.cc b/src/engine/renderer/opengl/renderer_opengl.cc index b25d43d..3a5fd44 100644 --- a/src/engine/renderer/opengl/renderer_opengl.cc +++ b/src/engine/renderer/opengl/renderer_opengl.cc @@ -48,6 +48,7 @@ RendererOpenGL::RendererOpenGL() = default; RendererOpenGL::~RendererOpenGL() { Shutdown(); + OnDestroy(); } void RendererOpenGL::Shutdown() { diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index c9019c1..75f983a 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -165,6 +165,8 @@ class RendererOpenGL final : public Renderer { bool InitCommon(); void ShutdownInternal(); + void OnDestroy(); + void ContextLost(); void DestroyAllResources(); diff --git a/src/engine/renderer/opengl/renderer_opengl_android.cc b/src/engine/renderer/opengl/renderer_opengl_android.cc index d3e94a0..2c36c71 100644 --- a/src/engine/renderer/opengl/renderer_opengl_android.cc +++ b/src/engine/renderer/opengl/renderer_opengl_android.cc @@ -14,6 +14,10 @@ bool RendererOpenGL::Initialize(ANativeWindow* window) { return StartRenderThread(); } +void RendererOpenGL::OnDestroy() { + ndk_helper::GLContext::GetInstance()->Invalidate(); +} + bool RendererOpenGL::InitInternal() { ndk_helper::GLContext* gl_context = ndk_helper::GLContext::GetInstance(); diff --git a/src/engine/renderer/opengl/renderer_opengl_linux.cc b/src/engine/renderer/opengl/renderer_opengl_linux.cc index 15ec965..5bb452a 100644 --- a/src/engine/renderer/opengl/renderer_opengl_linux.cc +++ b/src/engine/renderer/opengl/renderer_opengl_linux.cc @@ -18,6 +18,8 @@ bool RendererOpenGL::Initialize(Display* display, Window window) { return StartRenderThread(); } +void RendererOpenGL::OnDestroy() {} + bool RendererOpenGL::InitInternal() { // Create the OpenGL context. glx_context_ = diff --git a/src/engine/renderer/render_resource.h b/src/engine/renderer/render_resource.h index fb2413d..362c80f 100644 --- a/src/engine/renderer/render_resource.h +++ b/src/engine/renderer/render_resource.h @@ -15,6 +15,11 @@ class RenderResource { uint64_t resource_id() { return resource_id_; } + void SetRenderer(Renderer* renderer) { + renderer_ = renderer; + resource_id_ = 0; + } + protected: uint64_t resource_id_ = 0; Renderer* renderer_ = nullptr;