add events listener object, create kernel context and some gl resources

This commit is contained in:
2025-12-29 19:16:05 +01:00
parent 6830c61e31
commit 66df0e66e2
18 changed files with 556 additions and 38 deletions

View File

@@ -1,13 +1,153 @@
#include <jni.h>
#include <android/binder_ibinder_jni.h>
#include <android/hardware_buffer.h>
#include <aidl/com/omixlab/mosis/BnMosisService.h>
#include <aidl/com/omixlab/mosis/IMosisListener.h>
#include "egl_context.h"
#include "logger.h"
#include <glad/egl.h>
#include <glad/gles2.h>
#include <thread>
using namespace aidl::com::omixlab::mosis;
class NativeService : public BnMosisService {
class Texture
{
GLuint id;
public:
bool create(uint32_t width, uint32_t height)
{
glGenTextures(1, &id);
return true;
}
};
class RenderTarget
{
AHardwareBuffer* hardwareBuffer = nullptr;
GLuint m_framebuffer = 0;
GLuint texture = 0;
public:
bool create(uint32_t width, uint32_t height)
{
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
return false;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return true;
}
bool create_exported(uint32_t width, uint32_t height)
{
AHardwareBuffer_Desc desc = {};
desc.width = width;
desc.height = height;
desc.layers = 1;
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER;
if (AHardwareBuffer_allocate(&desc, &hardwareBuffer) != 0)
{
Logger::Log("Failed to allocate hardware buffer");
return false;
}
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, clientBuffer, nullptr);
if (eglImage == EGL_NO_IMAGE_KHR)
{
AHardwareBuffer_release(hardwareBuffer);
Logger::Log("Failed to create EGL image");
return false;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
bool status = (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return status;
}
[[nodiscard]] long hardware_buffer()
{
return reinterpret_cast<long>(hardwareBuffer);
}
void bind()
{
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
}
void unbind()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void destroy()
{
glDeleteTextures(1, &texture);
glDeleteFramebuffers(1, &m_framebuffer);
}
};
class Kernel
{
std::unique_ptr<egl::Context> m_egl_context;
std::unique_ptr<RenderTarget> m_render_target;
std::shared_ptr<IMosisListener> m_listener;
std::thread m_main_loop_thread;
void main_loop()
{
m_egl_context = std::make_unique<egl::Context>();
if (!m_egl_context->create())
{
Logger::Log("failed to create EGL context");
return;
}
m_render_target = std::make_unique<RenderTarget>();
if (!m_render_target->create_exported(1024, 1024))
{
Logger::Log("failed to create render target");
return;
}
m_render_target->bind();
m_listener->onServiceInitialized(true);
while (true)
{
m_listener->onFrameAvailable(m_render_target->hardware_buffer());
m_egl_context->swap();
}
}
public:
Kernel(const std::shared_ptr<IMosisListener>& listener) : m_listener(listener)
{
m_main_loop_thread = std::thread(&Kernel::main_loop, this);
}
};
class NativeService : public BnMosisService
{
std::unique_ptr<Kernel> m_kernel;
public:
NativeService() = default;
ndk::ScopedAStatus getNumber(int32_t *_aidl_return) override
@@ -15,15 +155,12 @@ public:
*_aidl_return = 100;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus initOS(bool *_aidl_return) override {
if (!m_egl_context)
ndk::ScopedAStatus initOS(const std::shared_ptr<IMosisListener>& listener,
bool *_aidl_return) override
{
if (!m_kernel)
{
m_egl_context = std::make_unique<egl::Context>();
*_aidl_return = m_egl_context->create();
}
else
{
Logger::Log("OS already initialized");
m_kernel = std::make_unique<Kernel>(listener);
*_aidl_return = true;
}
return ndk::ScopedAStatus::ok();
@@ -32,7 +169,8 @@ public:
extern "C"
JNIEXPORT jobject JNICALL
Java_com_omixlab_mosis_NativeService_getBinderNative(JNIEnv *env, jobject thiz) {
Java_com_omixlab_mosis_NativeService_getBinderNative(JNIEnv *env, jobject thiz)
{
static std::shared_ptr<NativeService> g_service = ndk::SharedRefBase::make<NativeService>();
return AIBinder_toJavaBinder(env, g_service->asBinder().get());
}