more refactoring
This commit is contained in:
@@ -16,7 +16,9 @@ add_library(mosis-service SHARED
|
||||
external_texture.cpp
|
||||
quad.cpp
|
||||
egl_context.cpp
|
||||
render_target.cpp
|
||||
logger.cpp
|
||||
kernel.cpp
|
||||
glad/src/egl.c
|
||||
glad/src/gles2.c)
|
||||
target_include_directories(mosis-service PUBLIC
|
||||
@@ -33,6 +35,8 @@ add_library(mosis-test SHARED
|
||||
external_texture.cpp
|
||||
quad.cpp
|
||||
egl_context.cpp
|
||||
render_target.cpp
|
||||
kernel.cpp
|
||||
logger.cpp
|
||||
glad/src/egl.c
|
||||
glad/src/gles2.c)
|
||||
|
||||
46
src/main/cpp/kernel.cpp
Normal file
46
src/main/cpp/kernel.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "kernel.h"
|
||||
#include "egl_context.h"
|
||||
#include "render_target.h"
|
||||
#include "logger.h"
|
||||
#include "aidl/com/omixlab/mosis/IMosisListener.h"
|
||||
#include <android/hardware_buffer.h>
|
||||
|
||||
using namespace aidl::com::omixlab::mosis;
|
||||
using namespace aidl::android::hardware;
|
||||
|
||||
void Kernel::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);
|
||||
m_aidl_buffer = std::make_unique<HardwareBuffer>();
|
||||
m_aidl_buffer->reset(m_render_target->hardware_buffer());
|
||||
m_listener->onBufferAvailable(*m_aidl_buffer);
|
||||
|
||||
while (true)
|
||||
{
|
||||
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glFinish();
|
||||
m_listener->onFrameAvailable();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
|
||||
Kernel::Kernel(const std::shared_ptr<IMosisListener> &listener) : m_listener(listener)
|
||||
{
|
||||
m_main_loop_thread = std::thread(&Kernel::main_loop, this);
|
||||
}
|
||||
|
||||
Kernel::~Kernel() = default;
|
||||
22
src/main/cpp/kernel.h
Normal file
22
src/main/cpp/kernel.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
class RenderTarget;
|
||||
namespace egl { class Context; }
|
||||
namespace aidl::com::omixlab::mosis { class IMosisListener; }
|
||||
namespace aidl::android::hardware { struct HardwareBuffer; }
|
||||
|
||||
class Kernel
|
||||
{
|
||||
std::unique_ptr<egl::Context> m_egl_context;
|
||||
std::unique_ptr<RenderTarget> m_render_target;
|
||||
std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener> m_listener;
|
||||
std::unique_ptr<aidl::android::hardware::HardwareBuffer> m_aidl_buffer;
|
||||
std::thread m_main_loop_thread;
|
||||
void main_loop();
|
||||
public:
|
||||
explicit Kernel(const std::shared_ptr<aidl::com::omixlab::mosis::IMosisListener>& listener);
|
||||
virtual ~Kernel();
|
||||
};
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <aidl/com/omixlab/mosis/BnMosisService.h>
|
||||
#include <aidl/com/omixlab/mosis/IMosisListener.h>
|
||||
#include <aidl/com/omixlab/mosis/BnMosisListener.h>
|
||||
#include "egl_context.h"
|
||||
#include "logger.h"
|
||||
#include "kernel.h"
|
||||
#include <glad/egl.h>
|
||||
#include <glad/gles2.h>
|
||||
#include <thread>
|
||||
@@ -24,136 +24,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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]] AHardwareBuffer* hardware_buffer()
|
||||
{
|
||||
return 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;
|
||||
HardwareBuffer m_aidl_buffer;
|
||||
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);
|
||||
m_aidl_buffer.reset(m_render_target->hardware_buffer());
|
||||
m_listener->onBufferAvailable(m_aidl_buffer);
|
||||
|
||||
while (true)
|
||||
{
|
||||
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glFinish();
|
||||
m_listener->onFrameAvailable();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
89
src/main/cpp/render_target.cpp
Normal file
89
src/main/cpp/render_target.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "render_target.h"
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <glad/egl.h>
|
||||
#include "logger.h"
|
||||
bool RenderTarget::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, nullptr);
|
||||
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 RenderTarget::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;
|
||||
}
|
||||
|
||||
AHardwareBuffer *RenderTarget::hardware_buffer()
|
||||
{
|
||||
return hardwareBuffer;
|
||||
}
|
||||
|
||||
void RenderTarget::bind()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
||||
}
|
||||
|
||||
void RenderTarget::unbind()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void RenderTarget::destroy()
|
||||
{
|
||||
glDeleteTextures(1, &texture);
|
||||
glDeleteFramebuffers(1, &m_framebuffer);
|
||||
}
|
||||
17
src/main/cpp/render_target.h
Normal file
17
src/main/cpp/render_target.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <glad/gles2.h>
|
||||
struct AHardwareBuffer;
|
||||
|
||||
class RenderTarget
|
||||
{
|
||||
AHardwareBuffer* hardwareBuffer = nullptr;
|
||||
GLuint m_framebuffer = 0;
|
||||
GLuint texture = 0;
|
||||
public:
|
||||
bool create(uint32_t width, uint32_t height);
|
||||
bool create_exported(uint32_t width, uint32_t height);
|
||||
[[nodiscard]] AHardwareBuffer* hardware_buffer();
|
||||
void bind();
|
||||
void unbind();
|
||||
void destroy();
|
||||
};
|
||||
Reference in New Issue
Block a user