Files
LayaNative2.0/Conch/source/napi/render/plugin_render.cpp
T
2024-07-12 11:44:27 +08:00

338 lines
11 KiB
C++

#include <stdint.h>
#include <unistd.h>
#include "plugin_render.h"
#include "../../napi/plugin_manager.h"
#include "../modules/TouchesNapi.h"
#include "../../napi/NAPIFun.cpp"
#include <assert.h>
#include "util/Log.h"
using namespace laya;
#ifdef __cplusplus
extern "C" {
#endif
PluginRender* PluginRender::instance_ = nullptr;
OH_NativeXComponent_Callback PluginRender::callback_;
uint64_t PluginRender::animationInterval_ = 16;
uint64_t PluginRender::lastTime = 0;
void OnSurfaceCreatedCB(OH_NativeXComponent* component, void* window)
{
LOGI("OnSurfaceCreatedCB");
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_SURFACE_CREATED, component, window);
}
void OnSurfaceChangedCB(OH_NativeXComponent* component, void* window)
{
LOGI("OnSurfaceChangedCB");
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_SURFACE_CHANGED, component, window);
}
void OnSurfaceDestroyedCB(OH_NativeXComponent* component, void* window)
{
LOGI("OnSurfaceDestroyedCB");
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_SURFACE_DESTROY, component, window);
}
void DispatchTouchEventCB(OH_NativeXComponent* component, void* window)
{
OH_NativeXComponent_TouchEvent* touchEvent = new(std::nothrow) OH_NativeXComponent_TouchEvent();
if (!touchEvent) {
LOGI("DispatchTouchEventCB::touchEvent alloc failed");
return;
}
int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, touchEvent);
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
PluginRender::GetInstance()->sendMsgToWorker(MessageType::WM_XCOMPONENT_TOUCH_EVENT, component, window, touchEvent);
} else {
delete touchEvent;
}
}
PluginRender::PluginRender() : component_(nullptr)
{
auto renderCallback = PluginRender::GetNXComponentCallback();
renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;
renderCallback->OnSurfaceChanged = OnSurfaceChangedCB;
renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
renderCallback->DispatchTouchEvent = DispatchTouchEventCB;
}
PluginRender* PluginRender::GetInstance()
{
if (instance_ == nullptr) {
instance_ = new PluginRender();
}
return instance_;
}
OH_NativeXComponent_Callback* PluginRender::GetNXComponentCallback()
{
return &PluginRender::callback_;
}
// static
void PluginRender::onMessageCallback(const uv_async_t* /* req */) {
void* window = nullptr;
WorkerMessageData msgData;
PluginRender* render = PluginRender::GetInstance();
while (true) {
//loop until all msg dispatch
if (!render->dequeue(reinterpret_cast<WorkerMessageData*>(&msgData))) {
// Queue has no data
break;
}
if ((msgData.type >= MessageType::WM_XCOMPONENT_SURFACE_CREATED) && (msgData.type <= MessageType::WM_XCOMPONENT_SURFACE_DESTROY)) {
OH_NativeXComponent* nativexcomponet = reinterpret_cast<OH_NativeXComponent*>(msgData.data);
// CC_ASSERT(nativexcomponet != nullptr);
if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_CREATED) {
render->OnSurfaceCreated(nativexcomponet, msgData.window);
} else if (msgData.type == MessageType::WM_XCOMPONENT_TOUCH_EVENT) {
render->DispatchTouchEvent(nativexcomponet, msgData.window, msgData.touchEvent);
} else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_CHANGED) {
render->OnSurfaceChanged(nativexcomponet, msgData.window);
} else if (msgData.type == MessageType::WM_XCOMPONENT_SURFACE_DESTROY) {
render->OnSurfaceDestroyed(nativexcomponet, msgData.window);
} else {
// CC_ASSERT(false);
}
continue;
}
if (msgData.type == MessageType::WM_APP_SHOW) {
render->OnShowNative();
} else if (msgData.type == MessageType::WM_APP_HIDE) {
render->OnHideNative();
} else if (msgData.type == MessageType::WM_APP_DESTROY) {
render->OnDestroyNative();
}
if(msgData.type == MessageType::WM_VSYNC) {
// render->runTask();
}
}
}
static uint64_t getCurrentMillSecond() {
struct timeval stCurrentTime;
gettimeofday(&stCurrentTime,NULL);
return stCurrentTime.tv_sec * 1000 + stCurrentTime.tv_usec / 1000; //millseconds
}
// static
void PluginRender::timerCb(uv_timer_t* handle)
{
// LOGI("PluginRender::timerCb, animationInterval_ is %{public}lu", animationInterval_);
if (PluginRender::GetInstance()->eglCore_ != nullptr) {
PluginRender::GetInstance()->eglCore_->Update();
NAPIFun::ConchNAPI_onDrawFrame();
}
}
void PluginRender::SetNativeXComponent(OH_NativeXComponent* component)
{
component_ = component;
OH_NativeXComponent_RegisterCallback(component_, &PluginRender::callback_);
}
void PluginRender::workerInit(napi_env env, uv_loop_t* loop) {
LOGI("PluginRender::workerInit");
workerLoop_ = loop;
if (workerLoop_) {
uv_async_init(workerLoop_, &messageSignal_, reinterpret_cast<uv_async_cb>(PluginRender::onMessageCallback));
if (!messageQueue_.empty()) {
triggerMessageSignal(); // trigger the signal to handle the pending message
}
}
}
void PluginRender::sendMsgToWorker(const MessageType& type, OH_NativeXComponent* component, void* window) {
WorkerMessageData data{type, static_cast<void*>(component), window};
enqueue(data);
}
void PluginRender::sendMsgToWorker(const MessageType& type, OH_NativeXComponent* component, void* window, OH_NativeXComponent_TouchEvent* touchEvent) {
WorkerMessageData data{type, static_cast<void*>(component), window, touchEvent};
enqueue(data);
}
void PluginRender::enqueue(const WorkerMessageData& msg) {
messageQueue_.enqueue(msg);
triggerMessageSignal();
}
bool PluginRender::dequeue(WorkerMessageData* msg) {
return messageQueue_.dequeue(msg);
}
void PluginRender::triggerMessageSignal() {
if(workerLoop_ != nullptr) {
// It is possible that when the message is sent, the worker thread has not yet started.
uv_async_send(&messageSignal_);
}
}
void PluginRender::run() {
LOGI("PluginRender::run");
if (workerLoop_) {
uv_timer_init(workerLoop_, &timerHandle_);
timerInited_ = true;
}
}
void PluginRender::changeFPS(uint64_t animationInterval) {
LOGI("PluginRender::changeFPS, animationInterval from %{public}lu to %{public}lu", animationInterval_, animationInterval);
animationInterval_ = animationInterval;
}
void PluginRender::OnSurfaceCreated(OH_NativeXComponent* component, void* window)
{
LOGI("PluginRender::OnSurfaceCreated");
eglCore_ = new EGLCore();
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
eglCore_->GLContextInit(window, width_, height_);
NAPIFun::ConchNAPI_OnGLReady(width_,height_);
}
}
void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window)
{
LOGI("PluginRender::OnSurfaceChanged");
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
NAPIFun::ConchNAPI_OnGLReady(width_,height_);
}
}
void PluginRender::OnSurfaceDestroyed(OH_NativeXComponent* component, void* window)
{
}
void PluginRender::DispatchTouchEvent(OH_NativeXComponent* component, void* window, OH_NativeXComponent_TouchEvent* touchEvent)
{
intptr_t ids[touchEvent->numPoints];
float xs[touchEvent->numPoints];
float ys[touchEvent->numPoints];
for (int i = 0; i < touchEvent->numPoints; i++) {
ids[i] = touchEvent->touchPoints[i].id;
xs[i] = touchEvent->touchPoints[i].x;
ys[i] = touchEvent->touchPoints[i].y;
LOGI("Touch Info : x = %{public}f, y = %{public}f", xs[i], ys[i]);
}
switch (touchEvent -> type) {
case OH_NATIVEXCOMPONENT_DOWN:
nativeHandleTouchDown(touchEvent->id, touchEvent->x,touchEvent->y);
LOGI("Touch Info : OH_NATIVEXCOMPONENT_DOWN");
break;
case OH_NATIVEXCOMPONENT_UP:
nativeHandleTouchUp(touchEvent->id, touchEvent->x,touchEvent->y);
LOGI("Touch Info : OH_NATIVEXCOMPONENT_UP");
break;
case OH_NATIVEXCOMPONENT_MOVE:
nativeHandleTouchMove(touchEvent->id, touchEvent->x,touchEvent->y);
LOGI("Touch Info : OH_NATIVEXCOMPONENT_MOVE");
break;
case OH_NATIVEXCOMPONENT_CANCEL:
nativeHandleTouchCancel(touchEvent->id, touchEvent->x,touchEvent->y);
LOGI("Touch Info : OH_NATIVEXCOMPONENT_CANCEL");
break;
case OH_NATIVEXCOMPONENT_UNKNOWN:
LOGI("Touch Info : OH_NATIVEXCOMPONENT_UNKNOWN");
break;
default:
LOGI("Touch Info : default");
break;
}
delete touchEvent;
}
void PluginRender::OnCreateNative(napi_env env, uv_loop_t* loop) {
LOGI("PluginRender::OnCreateNative");
}
void PluginRender::OnShowNative() {
LOGI("PluginRender::OnShowNative");
if (timerInited_) {
uv_timer_start(&timerHandle_, &PluginRender::timerCb, 0, 1);
}
JCAudioManager* am = JCAudioManager::GetInstance();
if(am->getMp3Mute() == false && am ->getMp3Stopped() == false)
{
auto pFunction = std::bind(&JCAudioManager::resumeMp3,am);
JCScriptRuntime::s_JSRT->m_pPoster->postToJS(pFunction);
}
laya::JCAudioManager::GetInstance()->m_pWavPlayer->resume();
}
void PluginRender::OnHideNative() {
LOGI("PluginRender::OnHideNative");
JCAudioManager* am =JCAudioManager::GetInstance();
if(am->getMp3Mute() == false && am->getMp3Stopped() == false)
{
auto pFunction = std::bind(&JCAudioManager::pauseMp3,am);
JCScriptRuntime::s_JSRT->m_pPoster->postToJS( pFunction );
}
laya::JCAudioManager::GetInstance()->m_pWavPlayer->pause();
if (timerInited_) {
uv_timer_stop(&timerHandle_);
}
}
void PluginRender::OnDestroyNative() {
LOGI("PluginRender::OnDestoryNative");
if (timerInited_) {
uv_timer_stop(&timerHandle_);
}
NAPIFun::ConchNAPI_ReleaseDLib();
}
napi_value PluginRender::Export(napi_env env, napi_value exports)
{
LOGI("PluginRender::Export");
// Register JS API
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("changeShape", PluginRender::NapiChangeShape),
DECLARE_NAPI_FUNCTION("drawTriangle", PluginRender::NapiDrawTriangle),
DECLARE_NAPI_FUNCTION("changeColor", PluginRender::NapiChangeColor),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
return exports;
}
napi_value PluginRender::NapiChangeShape(napi_env env, napi_callback_info info)
{
LOGI("PluginRender::NapiChangeShape");
PluginRender* instance = PluginRender::GetInstance();
if (instance) {
instance->eglCore_->Update();
}
return nullptr;
}
napi_value PluginRender::NapiDrawTriangle(napi_env env, napi_callback_info info)
{
LOGI("NapiDrawTriangle");
return nullptr;
}
napi_value PluginRender::NapiChangeColor(napi_env env, napi_callback_info info)
{
LOGI("NapiChangeColor");
return nullptr;
}
#ifdef __cplusplus
}
#endif