client egl context and viewport in kotlin UI

This commit is contained in:
2025-12-28 21:46:18 +01:00
parent 19400fd2b2
commit 6830c61e31
5 changed files with 175 additions and 15 deletions

View File

@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.22.1)
project("mosis")
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(ANDROID_SDK "/Users/omar/Library/Android/sdk")
set(BINDER_DIR "${ANDROID_SDK}/platforms/android-36/optional/libbinder_ndk_cpp")
@@ -14,7 +17,7 @@ add_library(mosis-service SHARED
target_include_directories(mosis-service PUBLIC
${CMAKE_CURRENT_LIST_DIR} ${BINDER_DIR} glad/include)
target_link_libraries(mosis-service
android log binder_ndk)
android log binder_ndk EGL GLESv2)
add_library(mosis-test SHARED
com/omixlab/mosis/IMosisService.cpp
@@ -27,4 +30,4 @@ add_library(mosis-test SHARED
target_include_directories(mosis-test PUBLIC
${CMAKE_CURRENT_LIST_DIR} ${BINDER_DIR} glad/include)
target_link_libraries(mosis-test
android log binder_ndk)
android log binder_ndk EGL GLESv2)

View File

@@ -2,8 +2,10 @@
#include "logger.h"
#include <glad/gles2.h>
#include <glad/egl.h>
#include <android/native_window_jni.h>
#include <vector>
bool egl::Context::create()
bool egl::Context::create(ANativeWindow* window)
{
int version = gladLoaderLoadEGL(EGL_NO_DISPLAY);
if (version == 0)
@@ -12,7 +14,7 @@ bool egl::Context::create()
return false;
}
if (m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
m_display == EGL_NO_DISPLAY)
m_display == EGL_NO_DISPLAY)
{
Logger::Log("eglGetDisplay failed");
return false;
@@ -24,14 +26,22 @@ bool egl::Context::create()
return false;
}
version = gladLoaderLoadEGL(EGL_DEFAULT_DISPLAY);
const EGLint config_attribs[] =
std::vector<EGLint> config_attribs =
{
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_NONE,
};
if (window)
{
config_attribs.append_range(std::to_array({
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
}));
}
config_attribs.push_back(EGL_NONE);
EGLint num_configs;
if (!eglChooseConfig(m_display, config_attribs, &m_config, 1, &num_configs) || num_configs == 0)
if (!eglChooseConfig(m_display, config_attribs.data(), &m_config, 1, &num_configs) || num_configs == 0)
{
Logger::Log("eglChooseConfig failed");
return false;
@@ -48,11 +58,22 @@ bool egl::Context::create()
Logger::Log("eglCreateContext failed");
return false;
}
if (!eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, m_context))
if (window)
{
m_surface = eglCreateWindowSurface(m_display, m_config, window, nullptr);
m_native_window = window;
}
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
{
Logger::Log("eglMakeCurrent failed");
return false;
}
int gl_version = gladLoaderLoadGLES2();
if (gl_version == 0)
{
Logger::Log("glad failed to load GLES2");
return false;
}
return true;
}
@@ -61,18 +82,36 @@ void egl::Context::destroy()
if (m_display != EGL_NO_DISPLAY)
{
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE)
{
eglDestroySurface(m_display, m_surface);
}
if (m_context != EGL_NO_CONTEXT)
{
eglDestroyContext(m_display, m_context);
}
if (m_native_window)
{
ANativeWindow_release(m_native_window);
}
eglTerminate(m_display);
}
m_display = EGL_NO_DISPLAY;
m_context = EGL_NO_CONTEXT;
m_config = EGL_NO_CONFIG_KHR;
m_surface = EGL_NO_SURFACE;
m_native_window = nullptr;
}
egl::Context::Context()
: m_display(EGL_NO_DISPLAY), m_config(EGL_NO_CONFIG_KHR), m_context(EGL_NO_CONTEXT)
egl::Context::Context() :
m_display(EGL_NO_DISPLAY), m_config(EGL_NO_CONFIG_KHR),
m_context(EGL_NO_CONTEXT), m_surface(EGL_NO_SURFACE),
m_native_window(nullptr)
{
Logger::Log("egl::Context::Context");
}
void egl::Context::swap()
{
eglSwapBuffers(m_display, m_surface);
}

View File

@@ -2,7 +2,9 @@
typedef void* EGLContext;
typedef void* EGLDisplay;
typedef void* EGLSurface;
typedef void* EGLConfig;
struct ANativeWindow;
namespace egl
{
@@ -10,10 +12,13 @@ class Context
{
EGLContext m_context;
EGLDisplay m_display;
EGLConfig m_config = nullptr;
EGLSurface m_surface;
EGLConfig m_config;
ANativeWindow* m_native_window;
public:
Context();
bool create();
bool create(ANativeWindow* window = nullptr);
void destroy();
void swap();
};
}

View File

@@ -1,11 +1,61 @@
#include <jni.h>
#include <android/binder_ibinder_jni.h>
#include <aidl/com/omixlab/mosis/IMosisService.h>
#include <android/native_window_jni.h>
#include "logger.h"
#include "egl_context.h"
#include <glad/gles2.h>
#include <memory>
#include <thread>
using namespace aidl::com::omixlab::mosis;
class Renderer
{
std::unique_ptr<egl::Context> m_egl_context;
std::thread m_render_loop;
bool m_active = false;
void render_loop(ANativeWindow* window)
{
m_egl_context = std::make_unique<egl::Context>();
if (m_egl_context->create(window))
{
m_active = true;
while (m_active)
{
render_frame();
}
}
else
{
Logger::Log("Failed to create EGL context");
}
}
void render_frame()
{
glClearColor(0.f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
m_egl_context->swap();
}
public:
bool create(ANativeWindow* window)
{
m_render_loop = std::thread(&Renderer::render_loop, this, window);
return true;
}
void destroy()
{
m_active = false;
if (m_render_loop.joinable())
m_render_loop.join();
m_egl_context->destroy();
m_egl_context.reset();
}
};
std::shared_ptr<IMosisService> g_service;
std::unique_ptr<Renderer> g_renderer;
extern "C"
JNIEXPORT void JNICALL
Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz, jobject binder) {
@@ -14,3 +64,23 @@ Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz,
g_service = IMosisService::fromBinder(spBinder);
Logger::Log("Service Connected");
}
extern "C"
JNIEXPORT void JNICALL
Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz, jobject surface) {
Logger::Log("setSurface");
if (!g_renderer)
{
g_renderer = std::make_unique<Renderer>();
g_renderer->create(ANativeWindow_fromSurface(env, surface));
}
}
extern "C"
JNIEXPORT void JNICALL
Java_com_omixlab_mosis_MainActivity_destroySurface(JNIEnv *env, jobject thiz) {
Logger::Log("destroySurface");
if (g_renderer)
{
g_renderer->destroy();
}
}