From 3a410775b553cb7a29089aa763041ff3abb0bdee Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 31 Dec 2025 16:12:43 +0100 Subject: [PATCH] async tasks --- src/main/cpp/egl_context.cpp | 32 +++++++++++++++++ src/main/cpp/egl_context.h | 1 + src/main/cpp/kernel.cpp | 17 +++++++-- src/main/cpp/kernel.h | 2 ++ src/main/cpp/mosis-service.cpp | 5 +++ src/main/cpp/mosis-test.cpp | 66 ++++++++++++++++++++++++++++------ 6 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/main/cpp/egl_context.cpp b/src/main/cpp/egl_context.cpp index 4ae53dd..4d36c99 100644 --- a/src/main/cpp/egl_context.cpp +++ b/src/main/cpp/egl_context.cpp @@ -69,6 +69,7 @@ bool egl::Context::create(ANativeWindow* window) if (window) { m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr); + ANativeWindow_acquire(window); m_native_window = window; } if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) @@ -129,3 +130,34 @@ void egl::Context::swap() { eglSwapBuffers(m_display, m_surface); } + +bool egl::Context::make_current(ANativeWindow* window) +{ + if (window == m_native_window) + { + return true; + } + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (m_surface != EGL_NO_SURFACE) + { + eglDestroySurface(m_display, m_surface); + m_surface = EGL_NO_SURFACE; + } + if (m_native_window) + { + ANativeWindow_release(m_native_window); + m_native_window = nullptr; + } + if (window) + { + m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr); + ANativeWindow_acquire(window); + m_native_window = window; + if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) + { + Logger::Log("eglMakeCurrent failed"); + return false; + } + } + return true; +} diff --git a/src/main/cpp/egl_context.h b/src/main/cpp/egl_context.h index a1b3a7f..f67414b 100644 --- a/src/main/cpp/egl_context.h +++ b/src/main/cpp/egl_context.h @@ -20,5 +20,6 @@ public: bool create(ANativeWindow* window = nullptr); void destroy(); void swap(); + bool make_current(ANativeWindow* window = nullptr); }; } diff --git a/src/main/cpp/kernel.cpp b/src/main/cpp/kernel.cpp index 3a800c5..779f3a2 100644 --- a/src/main/cpp/kernel.cpp +++ b/src/main/cpp/kernel.cpp @@ -30,10 +30,15 @@ void Kernel::main_loop() while (true) { - glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + static float angle = 0.0f; + angle += 0.1f; + glClearColor(fabs(sin(angle)), 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glFinish(); - m_listener->onFrameAvailable(); + { + std::lock_guard _lock(m_mutex); + m_listener->onFrameAvailable(); + } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } @@ -43,4 +48,12 @@ Kernel::Kernel(const std::shared_ptr &listener) : m_listener(lis m_main_loop_thread = std::thread(&Kernel::main_loop, this); } +void Kernel::set_listener(const std::shared_ptr &listener) +{ + std::lock_guard _lock(m_mutex); + m_listener = listener; + m_listener->onServiceInitialized(true); + m_listener->onBufferAvailable(*m_aidl_buffer); +} + Kernel::~Kernel() = default; diff --git a/src/main/cpp/kernel.h b/src/main/cpp/kernel.h index 0dda105..647aad7 100644 --- a/src/main/cpp/kernel.h +++ b/src/main/cpp/kernel.h @@ -14,9 +14,11 @@ class Kernel std::unique_ptr m_render_target; std::shared_ptr m_listener; std::unique_ptr m_aidl_buffer; + std::mutex m_mutex; std::thread m_main_loop_thread; void main_loop(); public: explicit Kernel(const std::shared_ptr& listener); virtual ~Kernel(); + void set_listener(const std::shared_ptr& listener); }; diff --git a/src/main/cpp/mosis-service.cpp b/src/main/cpp/mosis-service.cpp index 02d4bb9..ae402db 100644 --- a/src/main/cpp/mosis-service.cpp +++ b/src/main/cpp/mosis-service.cpp @@ -42,6 +42,11 @@ public: m_kernel = std::make_unique(listener); *_aidl_return = true; } + else + { + m_kernel->set_listener(listener); + *_aidl_return = true; + } return ndk::ScopedAStatus::ok(); } }; diff --git a/src/main/cpp/mosis-test.cpp b/src/main/cpp/mosis-test.cpp index 8795d5a..117bc16 100644 --- a/src/main/cpp/mosis-test.cpp +++ b/src/main/cpp/mosis-test.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include using namespace aidl::com::omixlab::mosis; using namespace aidl::android::hardware; @@ -28,6 +30,8 @@ class Renderer : public BnMosisListener std::unique_ptr m_quad_shader; std::unique_ptr m_quad; AHardwareBuffer* m_hwbuffer = nullptr; + std::vector> m_task_queue; + std::mutex m_task_mutex; std::thread m_render_loop; bool m_active = false; void render_loop(ANativeWindow* window) @@ -39,14 +43,7 @@ class Renderer : public BnMosisListener m_active = true; while (m_active) { - if (m_hwbuffer && !m_texture) - { - m_texture = std::make_unique(); - if (!m_texture->create(m_hwbuffer)) - { - Logger::Log("Failed to create texture"); - } - } + process_tasks(); render_frame(); } } @@ -62,9 +59,18 @@ class Renderer : public BnMosisListener m_quad = std::make_unique(); m_quad->create(); } + void process_tasks() + { + std::lock_guard _lock(m_task_mutex); + for (auto& task : m_task_queue) + { + task(); + } + m_task_queue.clear(); + } void render_frame() { - glClearColor(0.f, 0.5f, 0.5f, 1.0f); + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); if (m_texture) { @@ -88,9 +94,37 @@ public: m_active = false; if (m_render_loop.joinable()) m_render_loop.join(); - m_egl_context->destroy(); + if (m_egl_context) + m_egl_context->destroy(); m_egl_context.reset(); } + template + [[nodiscard]] std::future exec(T&& lambda) + { + std::lock_guard _lock(m_task_mutex); + auto promise = std::make_shared>(); + auto future = promise->get_future(); + m_task_queue.emplace_back( + [l=std::forward(lambda),p=std::move(promise)] + { + l(); + p->set_value(); + } + ); + return future; + } + template + void exec_async(T&& lambda) + { + std::lock_guard _lock(m_task_mutex); + m_task_queue.emplace_back(std::forward(lambda)); + } + void update_surface(ANativeWindow* window) + { + exec_async([this, window]{ + m_egl_context->make_current(window); + }); + } ndk::ScopedAStatus onServiceInitialized(bool in_success) override { return ndk::ScopedAStatus::ok(); @@ -104,6 +138,13 @@ public: { m_hwbuffer = in_buffer.get(); AHardwareBuffer_acquire(m_hwbuffer); + exec_async([this]{ + m_texture = std::make_unique(); + if (!m_texture->create(m_hwbuffer)) + { + Logger::Log("Failed to create texture"); + } + }); return ndk::ScopedAStatus::ok(); } }; @@ -144,6 +185,10 @@ Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, g_renderer = ndk::SharedRefBase::make(); g_renderer->create(ANativeWindow_fromSurface(env, surface)); } + else + { + g_renderer->update_surface(ANativeWindow_fromSurface(env, surface)); + } } extern "C" JNIEXPORT void JNICALL @@ -153,6 +198,7 @@ Java_com_omixlab_mosis_MainActivity_destroySurface(JNIEnv *env, jobject thiz) if (g_renderer) { g_renderer->destroy(); + g_renderer.reset(); } }