add events listener object, create kernel context and some gl resources
This commit is contained in:
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user