fix hardware buffer aidl
This commit is contained in:
@@ -14,7 +14,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.omixlab.mosis"
|
||||
minSdk = 33
|
||||
minSdk = 34
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
3
src/main/aidl/android/hardware/HardwareBuffer.aidl
Normal file
3
src/main/aidl/android/hardware/HardwareBuffer.aidl
Normal file
@@ -0,0 +1,3 @@
|
||||
package android.hardware;
|
||||
|
||||
@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h";
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.omixlab.mosis;
|
||||
|
||||
import android.hardware.HardwareBuffer;
|
||||
|
||||
// oneway = fire-and-forget (asynchronous)
|
||||
oneway interface IMosisListener {
|
||||
void onServiceInitialized(boolean success);
|
||||
void onFrameAvailable(long hardwareBufferPtr);
|
||||
void onBufferAvailable(in HardwareBuffer buffer);
|
||||
void onFrameAvailable();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,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 EGL GLESv2)
|
||||
android log binder_ndk EGL GLESv2 nativewindow)
|
||||
|
||||
add_library(mosis-test SHARED
|
||||
com/omixlab/mosis/IMosisService.cpp
|
||||
@@ -32,4 +32,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 EGL GLESv2)
|
||||
android log binder_ndk EGL GLESv2 nativewindow)
|
||||
|
||||
@@ -39,8 +39,11 @@ public:
|
||||
::ndk::ScopedAStatus onServiceInitialized(bool in_success) override {
|
||||
return _impl->onServiceInitialized(in_success);
|
||||
}
|
||||
::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override {
|
||||
return _impl->onFrameAvailable(in_hardwareBufferPtr);
|
||||
::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override {
|
||||
return _impl->onBufferAvailable(in_buffer);
|
||||
}
|
||||
::ndk::ScopedAStatus onFrameAvailable() override {
|
||||
return _impl->onFrameAvailable();
|
||||
}
|
||||
protected:
|
||||
private:
|
||||
|
||||
@@ -22,7 +22,8 @@ public:
|
||||
virtual ~BpMosisListener();
|
||||
|
||||
::ndk::ScopedAStatus onServiceInitialized(bool in_success) override;
|
||||
::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override;
|
||||
::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override;
|
||||
::ndk::ScopedAStatus onFrameAvailable() override;
|
||||
};
|
||||
} // namespace mosis
|
||||
} // namespace omixlab
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <android/binder_interface_utils.h>
|
||||
#include <android/hardware_buffer_aidl.h>
|
||||
#ifdef BINDER_STABILITY_SUPPORT
|
||||
#include <android/binder_stability.h>
|
||||
#endif // BINDER_STABILITY_SUPPORT
|
||||
@@ -32,7 +33,8 @@ public:
|
||||
virtual ~IMosisListener();
|
||||
|
||||
static constexpr uint32_t TRANSACTION_onServiceInitialized = FIRST_CALL_TRANSACTION + 0;
|
||||
static constexpr uint32_t TRANSACTION_onFrameAvailable = FIRST_CALL_TRANSACTION + 1;
|
||||
static constexpr uint32_t TRANSACTION_onBufferAvailable = FIRST_CALL_TRANSACTION + 1;
|
||||
static constexpr uint32_t TRANSACTION_onFrameAvailable = FIRST_CALL_TRANSACTION + 2;
|
||||
|
||||
static std::shared_ptr<IMosisListener> fromBinder(const ::ndk::SpAIBinder& binder);
|
||||
static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IMosisListener>& instance);
|
||||
@@ -40,14 +42,16 @@ public:
|
||||
static bool setDefaultImpl(const std::shared_ptr<IMosisListener>& impl);
|
||||
static const std::shared_ptr<IMosisListener>& getDefaultImpl();
|
||||
virtual ::ndk::ScopedAStatus onServiceInitialized(bool in_success) = 0;
|
||||
virtual ::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) = 0;
|
||||
virtual ::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) = 0;
|
||||
virtual ::ndk::ScopedAStatus onFrameAvailable() = 0;
|
||||
private:
|
||||
static std::shared_ptr<IMosisListener> default_impl;
|
||||
};
|
||||
class IMosisListenerDefault : public IMosisListener {
|
||||
public:
|
||||
::ndk::ScopedAStatus onServiceInitialized(bool in_success) override;
|
||||
::ndk::ScopedAStatus onFrameAvailable(int64_t in_hardwareBufferPtr) override;
|
||||
::ndk::ScopedAStatus onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) override;
|
||||
::ndk::ScopedAStatus onFrameAvailable() override;
|
||||
::ndk::SpAIBinder asBinder() override;
|
||||
bool isRemote() override;
|
||||
};
|
||||
|
||||
@@ -35,13 +35,19 @@ static binder_status_t _aidl_com_omixlab_mosis_IMosisListener_onTransact(AIBinde
|
||||
_aidl_ret_status = STATUS_OK;
|
||||
break;
|
||||
}
|
||||
case (FIRST_CALL_TRANSACTION + 1 /*onFrameAvailable*/): {
|
||||
int64_t in_hardwareBufferPtr;
|
||||
case (FIRST_CALL_TRANSACTION + 1 /*onBufferAvailable*/): {
|
||||
::aidl::android::hardware::HardwareBuffer in_buffer;
|
||||
|
||||
_aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_hardwareBufferPtr);
|
||||
_aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_buffer);
|
||||
if (_aidl_ret_status != STATUS_OK) break;
|
||||
|
||||
::ndk::ScopedAStatus _aidl_status = _aidl_impl->onFrameAvailable(in_hardwareBufferPtr);
|
||||
::ndk::ScopedAStatus _aidl_status = _aidl_impl->onBufferAvailable(in_buffer);
|
||||
_aidl_ret_status = STATUS_OK;
|
||||
break;
|
||||
}
|
||||
case (FIRST_CALL_TRANSACTION + 2 /*onFrameAvailable*/): {
|
||||
|
||||
::ndk::ScopedAStatus _aidl_status = _aidl_impl->onFrameAvailable();
|
||||
_aidl_ret_status = STATUS_OK;
|
||||
break;
|
||||
}
|
||||
@@ -87,7 +93,7 @@ BpMosisListener::~BpMosisListener() {}
|
||||
_aidl_status_return:
|
||||
return _aidl_status;
|
||||
}
|
||||
::ndk::ScopedAStatus BpMosisListener::onFrameAvailable(int64_t in_hardwareBufferPtr) {
|
||||
::ndk::ScopedAStatus BpMosisListener::onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& in_buffer) {
|
||||
binder_status_t _aidl_ret_status = STATUS_OK;
|
||||
::ndk::ScopedAStatus _aidl_status;
|
||||
::ndk::ScopedAParcel _aidl_in;
|
||||
@@ -96,12 +102,12 @@ BpMosisListener::~BpMosisListener() {}
|
||||
_aidl_ret_status = AIBinder_prepareTransaction(asBinderReference().get(), _aidl_in.getR());
|
||||
if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
|
||||
|
||||
_aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_hardwareBufferPtr);
|
||||
_aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_buffer);
|
||||
if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
|
||||
|
||||
_aidl_ret_status = AIBinder_transact(
|
||||
asBinderReference().get(),
|
||||
(FIRST_CALL_TRANSACTION + 1 /*onFrameAvailable*/),
|
||||
(FIRST_CALL_TRANSACTION + 1 /*onBufferAvailable*/),
|
||||
_aidl_in.getR(),
|
||||
_aidl_out.getR(),
|
||||
FLAG_ONEWAY
|
||||
@@ -110,7 +116,37 @@ BpMosisListener::~BpMosisListener() {}
|
||||
#endif // BINDER_STABILITY_SUPPORT
|
||||
);
|
||||
if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMosisListener::getDefaultImpl()) {
|
||||
_aidl_status = IMosisListener::getDefaultImpl()->onFrameAvailable(in_hardwareBufferPtr);
|
||||
_aidl_status = IMosisListener::getDefaultImpl()->onBufferAvailable(in_buffer);
|
||||
goto _aidl_status_return;
|
||||
}
|
||||
if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
|
||||
|
||||
_aidl_error:
|
||||
_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
|
||||
_aidl_status_return:
|
||||
return _aidl_status;
|
||||
}
|
||||
::ndk::ScopedAStatus BpMosisListener::onFrameAvailable() {
|
||||
binder_status_t _aidl_ret_status = STATUS_OK;
|
||||
::ndk::ScopedAStatus _aidl_status;
|
||||
::ndk::ScopedAParcel _aidl_in;
|
||||
::ndk::ScopedAParcel _aidl_out;
|
||||
|
||||
_aidl_ret_status = AIBinder_prepareTransaction(asBinderReference().get(), _aidl_in.getR());
|
||||
if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
|
||||
|
||||
_aidl_ret_status = AIBinder_transact(
|
||||
asBinderReference().get(),
|
||||
(FIRST_CALL_TRANSACTION + 2 /*onFrameAvailable*/),
|
||||
_aidl_in.getR(),
|
||||
_aidl_out.getR(),
|
||||
FLAG_ONEWAY
|
||||
#ifdef BINDER_STABILITY_SUPPORT
|
||||
| static_cast<int>(FLAG_PRIVATE_LOCAL)
|
||||
#endif // BINDER_STABILITY_SUPPORT
|
||||
);
|
||||
if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMosisListener::getDefaultImpl()) {
|
||||
_aidl_status = IMosisListener::getDefaultImpl()->onFrameAvailable();
|
||||
goto _aidl_status_return;
|
||||
}
|
||||
if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
|
||||
@@ -184,7 +220,12 @@ std::shared_ptr<IMosisListener> IMosisListener::default_impl = nullptr;
|
||||
_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
|
||||
return _aidl_status;
|
||||
}
|
||||
::ndk::ScopedAStatus IMosisListenerDefault::onFrameAvailable(int64_t /*in_hardwareBufferPtr*/) {
|
||||
::ndk::ScopedAStatus IMosisListenerDefault::onBufferAvailable(const ::aidl::android::hardware::HardwareBuffer& /*in_buffer*/) {
|
||||
::ndk::ScopedAStatus _aidl_status;
|
||||
_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
|
||||
return _aidl_status;
|
||||
}
|
||||
::ndk::ScopedAStatus IMosisListenerDefault::onFrameAvailable() {
|
||||
::ndk::ScopedAStatus _aidl_status;
|
||||
_aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
|
||||
return _aidl_status;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <android/hardware_buffer.h>
|
||||
#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 <glad/egl.h>
|
||||
@@ -10,6 +11,7 @@
|
||||
#include <thread>
|
||||
|
||||
using namespace aidl::com::omixlab::mosis;
|
||||
using namespace aidl::android::hardware;
|
||||
|
||||
class Texture
|
||||
{
|
||||
@@ -91,9 +93,9 @@ public:
|
||||
|
||||
return status;
|
||||
}
|
||||
[[nodiscard]] long hardware_buffer()
|
||||
[[nodiscard]] AHardwareBuffer* hardware_buffer()
|
||||
{
|
||||
return reinterpret_cast<long>(hardwareBuffer);
|
||||
return hardwareBuffer;
|
||||
}
|
||||
void bind()
|
||||
{
|
||||
@@ -115,6 +117,7 @@ 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()
|
||||
{
|
||||
@@ -132,13 +135,15 @@ class Kernel
|
||||
}
|
||||
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(m_render_target->hardware_buffer());
|
||||
m_listener->onFrameAvailable();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,55 @@
|
||||
#include <jni.h>
|
||||
#include <android/binder_ibinder_jni.h>
|
||||
#include <aidl/com/omixlab/mosis/IMosisService.h>
|
||||
#include <aidl/com/omixlab/mosis/IMosisListener.h>
|
||||
#include <aidl/com/omixlab/mosis/BnMosisListener.h>
|
||||
#include <android/native_window_jni.h>
|
||||
#include "logger.h"
|
||||
#include "egl_context.h"
|
||||
#include <glad/gles2.h>
|
||||
#include <glad/egl.h>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
using namespace aidl::com::omixlab::mosis;
|
||||
using namespace aidl::android::hardware;
|
||||
|
||||
class Renderer
|
||||
class Shader
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class ImportedTexture
|
||||
{
|
||||
GLuint texture = 0;
|
||||
public:
|
||||
bool create(AHardwareBuffer* hardwareBuffer)
|
||||
{
|
||||
AHardwareBuffer_Desc desc{};
|
||||
AHardwareBuffer_describe(hardwareBuffer, &desc);
|
||||
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
|
||||
EGLImageKHR eglImage = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
|
||||
EGL_NATIVE_BUFFER_ANDROID, clientBuffer, nullptr);
|
||||
if (eglImage == EGL_NO_IMAGE_KHR)
|
||||
{
|
||||
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);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Renderer : public BnMosisListener
|
||||
{
|
||||
std::unique_ptr<egl::Context> m_egl_context;
|
||||
std::unique_ptr<ImportedTexture> m_texture;
|
||||
AHardwareBuffer* m_hwbuffer = nullptr;
|
||||
std::thread m_render_loop;
|
||||
bool m_active = false;
|
||||
void render_loop(ANativeWindow* window)
|
||||
@@ -23,6 +60,14 @@ class Renderer
|
||||
m_active = true;
|
||||
while (m_active)
|
||||
{
|
||||
if (m_hwbuffer && !m_texture)
|
||||
{
|
||||
m_texture = std::make_unique<ImportedTexture>();
|
||||
if (!m_texture->create(m_hwbuffer))
|
||||
{
|
||||
Logger::Log("Failed to create texture");
|
||||
}
|
||||
}
|
||||
render_frame();
|
||||
}
|
||||
}
|
||||
@@ -35,9 +80,14 @@ class Renderer
|
||||
{
|
||||
glClearColor(0.f, 0.5f, 0.5f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (m_texture)
|
||||
{
|
||||
|
||||
}
|
||||
m_egl_context->swap();
|
||||
}
|
||||
public:
|
||||
Renderer() = default;
|
||||
bool create(ANativeWindow* window)
|
||||
{
|
||||
m_render_loop = std::thread(&Renderer::render_loop, this, window);
|
||||
@@ -51,10 +101,25 @@ public:
|
||||
m_egl_context->destroy();
|
||||
m_egl_context.reset();
|
||||
}
|
||||
ndk::ScopedAStatus onServiceInitialized(bool in_success) override
|
||||
{
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
ndk::ScopedAStatus onFrameAvailable() override
|
||||
{
|
||||
Logger::Log("onFrameAvailable");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
ndk::ScopedAStatus onBufferAvailable(const HardwareBuffer &in_buffer) override
|
||||
{
|
||||
m_hwbuffer = in_buffer.get();
|
||||
AHardwareBuffer_acquire(m_hwbuffer);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<IMosisService> g_service;
|
||||
std::unique_ptr<Renderer> g_renderer;
|
||||
std::shared_ptr<Renderer> g_renderer;
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
@@ -67,6 +132,17 @@ Java_com_omixlab_mosis_MainActivity_serviceConnected(JNIEnv *env, jobject thiz,
|
||||
Logger::Log("Service Connected");
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_omixlab_mosis_MainActivity_initOS(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
if (g_service && g_renderer)
|
||||
{
|
||||
bool result{};
|
||||
g_service->initOS(g_renderer, &result);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz,
|
||||
@@ -75,7 +151,7 @@ Java_com_omixlab_mosis_MainActivity_setSurface(JNIEnv *env, jobject thiz,
|
||||
Logger::Log("setSurface");
|
||||
if (!g_renderer)
|
||||
{
|
||||
g_renderer = std::make_unique<Renderer>();
|
||||
g_renderer = ndk::SharedRefBase::make<Renderer>();
|
||||
g_renderer->create(ANativeWindow_fromSurface(env, surface));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,24 +65,6 @@ class MainActivity : ComponentActivity() {
|
||||
Log.d("MosisTest", "surfaceDestroyed")
|
||||
}
|
||||
}
|
||||
val listener = object : IMosisListener.Stub() {
|
||||
override fun onServiceInitialized(success: Boolean) {
|
||||
Log.d("MosisTest", "onServiceInitialized: $success")
|
||||
|
||||
}
|
||||
|
||||
override fun onFrameAvailable(hardwareBufferPtr: Long) {
|
||||
Log.d("MosisTest", "onFrameAvailable: $hardwareBufferPtr")
|
||||
}
|
||||
}
|
||||
fun initOS()
|
||||
{
|
||||
remote_service?.let { service ->
|
||||
val result = service.initOS(listener)
|
||||
Log.d("MosisTest", "InitOS returned: $result")
|
||||
buttonText.value = if (result) "OS Initialized" else "OS Not Initialized"
|
||||
}
|
||||
}
|
||||
fun startRemoteService() {
|
||||
val intent = Intent("com.omixlab.mosis.SERVICE")
|
||||
intent.setPackage("com.omixlab.mosis")
|
||||
@@ -129,4 +111,5 @@ class MainActivity : ComponentActivity() {
|
||||
external fun serviceConnected(binder: IBinder)
|
||||
external fun setSurface(surface: Surface)
|
||||
external fun destroySurface()
|
||||
external fun initOS()
|
||||
}
|
||||
Reference in New Issue
Block a user