async tasks
This commit is contained in:
@@ -69,6 +69,7 @@ bool egl::Context::create(ANativeWindow* window)
|
|||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr);
|
m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr);
|
||||||
|
ANativeWindow_acquire(window);
|
||||||
m_native_window = window;
|
m_native_window = window;
|
||||||
}
|
}
|
||||||
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
|
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
|
||||||
@@ -129,3 +130,34 @@ void egl::Context::swap()
|
|||||||
{
|
{
|
||||||
eglSwapBuffers(m_display, m_surface);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,5 +20,6 @@ public:
|
|||||||
bool create(ANativeWindow* window = nullptr);
|
bool create(ANativeWindow* window = nullptr);
|
||||||
void destroy();
|
void destroy();
|
||||||
void swap();
|
void swap();
|
||||||
|
bool make_current(ANativeWindow* window = nullptr);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,15 @@ void Kernel::main_loop()
|
|||||||
|
|
||||||
while (true)
|
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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
glFinish();
|
glFinish();
|
||||||
m_listener->onFrameAvailable();
|
{
|
||||||
|
std::lock_guard _lock(m_mutex);
|
||||||
|
m_listener->onFrameAvailable();
|
||||||
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,4 +48,12 @@ Kernel::Kernel(const std::shared_ptr<IMosisListener> &listener) : m_listener(lis
|
|||||||
m_main_loop_thread = std::thread(&Kernel::main_loop, this);
|
m_main_loop_thread = std::thread(&Kernel::main_loop, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kernel::set_listener(const std::shared_ptr<IMosisListener> &listener)
|
||||||
|
{
|
||||||
|
std::lock_guard _lock(m_mutex);
|
||||||
|
m_listener = listener;
|
||||||
|
m_listener->onServiceInitialized(true);
|
||||||
|
m_listener->onBufferAvailable(*m_aidl_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
Kernel::~Kernel() = default;
|
Kernel::~Kernel() = default;
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ class Kernel
|
|||||||
std::unique_ptr<RenderTarget> m_render_target;
|
std::unique_ptr<RenderTarget> m_render_target;
|
||||||
std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener> m_listener;
|
std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener> m_listener;
|
||||||
std::unique_ptr<aidl::android::hardware::HardwareBuffer> m_aidl_buffer;
|
std::unique_ptr<aidl::android::hardware::HardwareBuffer> m_aidl_buffer;
|
||||||
|
std::mutex m_mutex;
|
||||||
std::thread m_main_loop_thread;
|
std::thread m_main_loop_thread;
|
||||||
void main_loop();
|
void main_loop();
|
||||||
public:
|
public:
|
||||||
explicit Kernel(const std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener>& listener);
|
explicit Kernel(const std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener>& listener);
|
||||||
virtual ~Kernel();
|
virtual ~Kernel();
|
||||||
|
void set_listener(const std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener>& listener);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ public:
|
|||||||
m_kernel = std::make_unique<Kernel>(listener);
|
m_kernel = std::make_unique<Kernel>(listener);
|
||||||
*_aidl_return = true;
|
*_aidl_return = true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_kernel->set_listener(listener);
|
||||||
|
*_aidl_return = true;
|
||||||
|
}
|
||||||
return ndk::ScopedAStatus::ok();
|
return ndk::ScopedAStatus::ok();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <future>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
using namespace aidl::com::omixlab::mosis;
|
using namespace aidl::com::omixlab::mosis;
|
||||||
using namespace aidl::android::hardware;
|
using namespace aidl::android::hardware;
|
||||||
@@ -28,6 +30,8 @@ class Renderer : public BnMosisListener
|
|||||||
std::unique_ptr<Shader> m_quad_shader;
|
std::unique_ptr<Shader> m_quad_shader;
|
||||||
std::unique_ptr<Quad> m_quad;
|
std::unique_ptr<Quad> m_quad;
|
||||||
AHardwareBuffer* m_hwbuffer = nullptr;
|
AHardwareBuffer* m_hwbuffer = nullptr;
|
||||||
|
std::vector<std::function<void()>> m_task_queue;
|
||||||
|
std::mutex m_task_mutex;
|
||||||
std::thread m_render_loop;
|
std::thread m_render_loop;
|
||||||
bool m_active = false;
|
bool m_active = false;
|
||||||
void render_loop(ANativeWindow* window)
|
void render_loop(ANativeWindow* window)
|
||||||
@@ -39,14 +43,7 @@ class Renderer : public BnMosisListener
|
|||||||
m_active = true;
|
m_active = true;
|
||||||
while (m_active)
|
while (m_active)
|
||||||
{
|
{
|
||||||
if (m_hwbuffer && !m_texture)
|
process_tasks();
|
||||||
{
|
|
||||||
m_texture = std::make_unique<ExternalTexture>();
|
|
||||||
if (!m_texture->create(m_hwbuffer))
|
|
||||||
{
|
|
||||||
Logger::Log("Failed to create texture");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
render_frame();
|
render_frame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,9 +59,18 @@ class Renderer : public BnMosisListener
|
|||||||
m_quad = std::make_unique<Quad>();
|
m_quad = std::make_unique<Quad>();
|
||||||
m_quad->create();
|
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()
|
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);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
if (m_texture)
|
if (m_texture)
|
||||||
{
|
{
|
||||||
@@ -88,9 +94,37 @@ public:
|
|||||||
m_active = false;
|
m_active = false;
|
||||||
if (m_render_loop.joinable())
|
if (m_render_loop.joinable())
|
||||||
m_render_loop.join();
|
m_render_loop.join();
|
||||||
m_egl_context->destroy();
|
if (m_egl_context)
|
||||||
|
m_egl_context->destroy();
|
||||||
m_egl_context.reset();
|
m_egl_context.reset();
|
||||||
}
|
}
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] std::future<void> exec(T&& lambda)
|
||||||
|
{
|
||||||
|
std::lock_guard _lock(m_task_mutex);
|
||||||
|
auto promise = std::make_shared<std::promise<void>>();
|
||||||
|
auto future = promise->get_future();
|
||||||
|
m_task_queue.emplace_back(
|
||||||
|
[l=std::forward<T>(lambda),p=std::move(promise)]
|
||||||
|
{
|
||||||
|
l();
|
||||||
|
p->set_value();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
void exec_async(T&& lambda)
|
||||||
|
{
|
||||||
|
std::lock_guard _lock(m_task_mutex);
|
||||||
|
m_task_queue.emplace_back(std::forward<T>(lambda));
|
||||||
|
}
|
||||||
|
void update_surface(ANativeWindow* window)
|
||||||
|
{
|
||||||
|
exec_async([this, window]{
|
||||||
|
m_egl_context->make_current(window);
|
||||||
|
});
|
||||||
|
}
|
||||||
ndk::ScopedAStatus onServiceInitialized(bool in_success) override
|
ndk::ScopedAStatus onServiceInitialized(bool in_success) override
|
||||||
{
|
{
|
||||||
return ndk::ScopedAStatus::ok();
|
return ndk::ScopedAStatus::ok();
|
||||||
@@ -104,6 +138,13 @@ public:
|
|||||||
{
|
{
|
||||||
m_hwbuffer = in_buffer.get();
|
m_hwbuffer = in_buffer.get();
|
||||||
AHardwareBuffer_acquire(m_hwbuffer);
|
AHardwareBuffer_acquire(m_hwbuffer);
|
||||||
|
exec_async([this]{
|
||||||
|
m_texture = std::make_unique<ExternalTexture>();
|
||||||
|
if (!m_texture->create(m_hwbuffer))
|
||||||
|
{
|
||||||
|
Logger::Log("Failed to create texture");
|
||||||
|
}
|
||||||
|
});
|
||||||
return ndk::ScopedAStatus::ok();
|
return ndk::ScopedAStatus::ok();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -144,6 +185,10 @@ Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz,
|
|||||||
g_renderer = ndk::SharedRefBase::make<Renderer>();
|
g_renderer = ndk::SharedRefBase::make<Renderer>();
|
||||||
g_renderer->create(ANativeWindow_fromSurface(env, surface));
|
g_renderer->create(ANativeWindow_fromSurface(env, surface));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_renderer->update_surface(ANativeWindow_fromSurface(env, surface));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
@@ -153,6 +198,7 @@ Java_com_omixlab_mosis_MainActivity_destroySurface(JNIEnv *env, jobject thiz)
|
|||||||
if (g_renderer)
|
if (g_renderer)
|
||||||
{
|
{
|
||||||
g_renderer->destroy();
|
g_renderer->destroy();
|
||||||
|
g_renderer.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user