Implement 2D graphic API (#87)
* Implement 2D graphic library based on LittlevGL * Add lvgl license file
This commit is contained in:
39
core/iwasm/lib/native/extension/gui/wamr_gui.inl
Normal file
39
core/iwasm/lib/native/extension/gui/wamr_gui.inl
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* button */
|
||||
EXPORT_WASM_API(wasm_btn_native_call),
|
||||
|
||||
/* obj */
|
||||
EXPORT_WASM_API(wasm_obj_native_call),
|
||||
|
||||
/* label */
|
||||
EXPORT_WASM_API(wasm_label_native_call),
|
||||
|
||||
/* cont */
|
||||
//EXPORT_WASM_API(wasm_cont_native_call),
|
||||
|
||||
/* page */
|
||||
//EXPORT_WASM_API(wasm_page_native_call),
|
||||
|
||||
/* list */
|
||||
EXPORT_WASM_API(wasm_list_native_call),
|
||||
|
||||
/* drop down list */
|
||||
//EXPORT_WASM_API(wasm_ddlist_native_call),
|
||||
|
||||
/* check box */
|
||||
EXPORT_WASM_API(wasm_cb_native_call),
|
||||
25
core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake
Normal file
25
core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
set (THIRD_PARTY_DIR ${WASM_LIB_GUI_DIR}/../../../3rdparty)
|
||||
|
||||
include_directories(${WASM_LIB_GUI_DIR} ${THIRD_PARTY_DIR} ${THIRD_PARTY_DIR}/lvgl)
|
||||
|
||||
file (GLOB_RECURSE lvgl_source ${THIRD_PARTY_DIR}/lvgl/*.c)
|
||||
file (GLOB_RECURSE wrapper_source ${WASM_LIB_GUI_DIR}/*.c)
|
||||
|
||||
set (WASM_LIB_GUI_SOURCE ${wrapper_source} ${lvgl_source})
|
||||
|
||||
57
core/iwasm/lib/native/extension/gui/wgl_btn_wrapper.c
Normal file
57
core/iwasm/lib/native/extension/gui/wgl_btn_wrapper.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "native_interface.h"
|
||||
#include "lvgl.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wgl_native_utils.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Button widget native function wrappers
|
||||
* -------------------------------------------------------------------------*/
|
||||
static int32 _btn_create(lv_obj_t *par, lv_obj_t *copy)
|
||||
{
|
||||
return wgl_native_wigdet_create(WIDGET_TYPE_BTN, par, copy);
|
||||
}
|
||||
|
||||
static WGLNativeFuncDef btn_native_func_defs[] = {
|
||||
{ BTN_FUNC_ID_CREATE, _btn_create, HAS_RET, 2, {0 | NULL_OK, 1 | NULL_OK, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_SET_TOGGLE, lv_btn_set_toggle, NO_RET, 2, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_SET_STATE, lv_btn_set_state, NO_RET, 2, {0, -1}, {-1} },
|
||||
// { BTN_FUNC_ID_SET_STYLE, _btn_set_style, NO_RET, 2, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_SET_INK_IN_TIME, lv_btn_set_ink_in_time, NO_RET, 2, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_SET_INK_OUT_TIME, lv_btn_set_ink_out_time, NO_RET, 2, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_SET_INK_WAIT_TIME, lv_btn_set_ink_wait_time, NO_RET, 2, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_GET_INK_IN_TIME, lv_btn_get_ink_in_time, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_GET_INK_OUT_TIME, lv_btn_get_ink_out_time, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_GET_INK_WAIT_TIME, lv_btn_get_ink_wait_time, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_GET_STATE, lv_btn_get_state, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_GET_TOGGLE, lv_btn_get_toggle, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ BTN_FUNC_ID_TOGGLE, lv_btn_toggle, NO_RET, 1, {0, -1}, {-1} },
|
||||
|
||||
};
|
||||
|
||||
/*************** Native Interface to Wasm App ***********/
|
||||
void wasm_btn_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
{
|
||||
uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
||||
wgl_native_func_call(btn_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argc);
|
||||
}
|
||||
73
core/iwasm/lib/native/extension/gui/wgl_cb_wrapper.c
Normal file
73
core/iwasm/lib/native/extension/gui/wgl_cb_wrapper.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "wasm_export.h"
|
||||
#include "native_interface.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wgl_native_utils.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Label widget native function wrappers
|
||||
* -------------------------------------------------------------------------*/
|
||||
static int32 _cb_create(lv_obj_t *par, lv_obj_t *copy)
|
||||
{
|
||||
return wgl_native_wigdet_create(WIDGET_TYPE_CB, par, copy);
|
||||
}
|
||||
|
||||
static int32 _cb_get_text_length(lv_obj_t *cb)
|
||||
{
|
||||
const char *text = lv_cb_get_text(cb);
|
||||
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
return strlen(text);
|
||||
}
|
||||
|
||||
static int32 _cb_get_text(lv_obj_t *cb, char *buffer, int buffer_len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst();
|
||||
const char *text = lv_cb_get_text(cb);
|
||||
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
strncpy(buffer, text, buffer_len - 1);
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
|
||||
return addr_native_to_app(buffer);
|
||||
}
|
||||
|
||||
static WGLNativeFuncDef cb_native_func_defs[] = {
|
||||
{ CB_FUNC_ID_CREATE, _cb_create, HAS_RET, 2, {0 | NULL_OK, 1 | NULL_OK, -1}, {-1} },
|
||||
{ CB_FUNC_ID_SET_TEXT, lv_cb_set_text, NO_RET, 2, {0, -1}, {1, -1} },
|
||||
{ CB_FUNC_ID_SET_STATIC_TEXT, lv_cb_set_static_text, NO_RET, 2, {0, -1}, {1, -1} },
|
||||
{ CB_FUNC_ID_GET_TEXT_LENGTH, _cb_get_text_length, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ CB_FUNC_ID_GET_TEXT, _cb_get_text, HAS_RET, 3, {0, -1}, {1, -1} },
|
||||
};
|
||||
|
||||
/*************** Native Interface to Wasm App ***********/
|
||||
void wasm_cb_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
{
|
||||
uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
||||
wgl_native_func_call(cb_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argc);
|
||||
}
|
||||
18
core/iwasm/lib/native/extension/gui/wgl_cont_wrapper.c
Normal file
18
core/iwasm/lib/native/extension/gui/wgl_cont_wrapper.c
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "module_wasm_app.h"
|
||||
72
core/iwasm/lib/native/extension/gui/wgl_label_wrapper.c
Normal file
72
core/iwasm/lib/native/extension/gui/wgl_label_wrapper.c
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "wasm_export.h"
|
||||
#include "native_interface.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wgl_native_utils.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Label widget native function wrappers
|
||||
* -------------------------------------------------------------------------*/
|
||||
static int32 _label_create(lv_obj_t *par, lv_obj_t *copy)
|
||||
{
|
||||
return wgl_native_wigdet_create(WIDGET_TYPE_LABEL, par, copy);
|
||||
}
|
||||
|
||||
static int32 _label_get_text_length(lv_obj_t *label)
|
||||
{
|
||||
char *text = lv_label_get_text(label);
|
||||
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
return strlen(text);
|
||||
}
|
||||
|
||||
static int32 _label_get_text(lv_obj_t *label, char *buffer, int buffer_len)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst();
|
||||
char *text = lv_label_get_text(label);
|
||||
|
||||
if (text == NULL)
|
||||
return 0;
|
||||
|
||||
strncpy(buffer, text, buffer_len - 1);
|
||||
buffer[buffer_len - 1] = '\0';
|
||||
|
||||
return addr_native_to_app(buffer);
|
||||
}
|
||||
|
||||
static WGLNativeFuncDef label_native_func_defs[] = {
|
||||
{ LABEL_FUNC_ID_CREATE, _label_create, HAS_RET, 2, {0 | NULL_OK, 1 | NULL_OK, -1}, {-1} },
|
||||
{ LABEL_FUNC_ID_SET_TEXT, lv_label_set_text, NO_RET, 2, {0, -1}, {1, -1} },
|
||||
{ LABEL_FUNC_ID_GET_TEXT_LENGTH, _label_get_text_length, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ LABEL_FUNC_ID_GET_TEXT, _label_get_text, HAS_RET, 3, {0, -1}, {1, -1} },
|
||||
};
|
||||
|
||||
/*************** Native Interface to Wasm App ***********/
|
||||
void wasm_label_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
{
|
||||
uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
||||
wgl_native_func_call(label_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argc);
|
||||
}
|
||||
63
core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c
Normal file
63
core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "native_interface.h"
|
||||
#include "lvgl.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wgl_native_utils.h"
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* List widget native function wrappers
|
||||
* -------------------------------------------------------------------------*/
|
||||
static int32 _list_create(lv_obj_t *par, lv_obj_t *copy)
|
||||
{
|
||||
return wgl_native_wigdet_create(WIDGET_TYPE_LIST, par, copy);
|
||||
}
|
||||
|
||||
static int32 _list_add_btn(lv_obj_t *list, const char *text)
|
||||
{
|
||||
uint32 btn_obj_id;
|
||||
lv_obj_t *btn;
|
||||
|
||||
btn = lv_list_add_btn(list, NULL, text);
|
||||
|
||||
if (btn == NULL)
|
||||
return 0;
|
||||
|
||||
if (wgl_native_add_object(btn,
|
||||
app_manager_get_module_id(Module_WASM_App),
|
||||
&btn_obj_id))
|
||||
return btn_obj_id; /* success return */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WGLNativeFuncDef list_native_func_defs[] = {
|
||||
{ LIST_FUNC_ID_CREATE, _list_create, HAS_RET, 2, {0 | NULL_OK, 1 | NULL_OK, -1}, {-1} },
|
||||
{ LIST_FUNC_ID_ADD_BTN, _list_add_btn, HAS_RET, 2, {0, -1}, {1, -1} },
|
||||
};
|
||||
|
||||
/*************** Native Interface to Wasm App ***********/
|
||||
void wasm_list_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
{
|
||||
uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
||||
wgl_native_func_call(list_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argc);
|
||||
}
|
||||
201
core/iwasm/lib/native/extension/gui/wgl_native_utils.c
Normal file
201
core/iwasm/lib/native/extension/gui/wgl_native_utils.c
Normal file
@ -0,0 +1,201 @@
|
||||
|
||||
|
||||
#include "wgl_native_utils.h"
|
||||
#include "lvgl.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define THROW_EXC(msg) wasm_runtime_set_exception(get_module_inst(), msg);
|
||||
|
||||
void
|
||||
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
|
||||
|
||||
uint32 wgl_native_wigdet_create(int8 widget_type, lv_obj_t *par, lv_obj_t *copy)
|
||||
{
|
||||
uint32 obj_id;
|
||||
lv_obj_t *wigdet;
|
||||
|
||||
//TODO: limit total widget number
|
||||
|
||||
if (par == NULL)
|
||||
par = lv_disp_get_scr_act(NULL);
|
||||
|
||||
if (widget_type == WIDGET_TYPE_BTN)
|
||||
wigdet = lv_btn_create(par, copy);
|
||||
else if (widget_type == WIDGET_TYPE_LABEL)
|
||||
wigdet = lv_label_create(par, copy);
|
||||
else if (widget_type == WIDGET_TYPE_CB)
|
||||
wigdet = lv_cb_create(par, copy);
|
||||
else if (widget_type == WIDGET_TYPE_LIST)
|
||||
wigdet = lv_list_create(par, copy);
|
||||
else if (widget_type == WIDGET_TYPE_DDLIST)
|
||||
wigdet = lv_ddlist_create(par, copy);
|
||||
|
||||
if (wigdet == NULL)
|
||||
return 0;
|
||||
|
||||
if (wgl_native_add_object(wigdet,
|
||||
app_manager_get_module_id(Module_WASM_App),
|
||||
&obj_id))
|
||||
return obj_id; /* success return */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void invokeNative(intptr_t argv[], uint32 argc, void (*native_code)())
|
||||
{
|
||||
switch(argc) {
|
||||
case 0:
|
||||
native_code();
|
||||
break;
|
||||
case 1:
|
||||
native_code(argv[0]);
|
||||
break;
|
||||
case 2:
|
||||
native_code(argv[0], argv[1]);
|
||||
break;
|
||||
case 3:
|
||||
native_code(argv[0], argv[1], argv[2]);
|
||||
break;
|
||||
case 4:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3]);
|
||||
break;
|
||||
case 5:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
break;
|
||||
case 6:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
|
||||
break;
|
||||
case 7:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
|
||||
argv[6]);
|
||||
break;
|
||||
case 8:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
|
||||
argv[6], argv[7]);
|
||||
break;
|
||||
case 9:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
|
||||
argv[6], argv[7], argv[8]);
|
||||
break;
|
||||
case 10:
|
||||
native_code(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5],
|
||||
argv[6], argv[7], argv[8], argv[9]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* FIXME: If this happen, add more cases. */
|
||||
wasm_runtime_set_exception(get_module_inst(),
|
||||
"the argument number of native function exceeds maximum");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*GenericFunctionPointer)();
|
||||
typedef int32 (*Int32FuncPtr)(intptr_t *, uint32, GenericFunctionPointer);
|
||||
typedef void (*VoidFuncPtr)(intptr_t *, uint32, GenericFunctionPointer);
|
||||
|
||||
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative;
|
||||
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative;
|
||||
|
||||
void wgl_native_func_call(WGLNativeFuncDef *funcs,
|
||||
uint32 size,
|
||||
int32 func_id,
|
||||
uint32 argv_offset,
|
||||
uint32 argc)
|
||||
{
|
||||
WGLNativeFuncDef *func_def = funcs;
|
||||
WGLNativeFuncDef *func_def_end = func_def + size;
|
||||
uint32 *argv;
|
||||
wasm_module_inst_t module_inst = get_module_inst();
|
||||
|
||||
if (!validate_app_addr(argv_offset, argc * sizeof(uint32)))
|
||||
return;
|
||||
|
||||
argv = addr_app_to_native(argv_offset);
|
||||
|
||||
while (func_def < func_def_end) {
|
||||
if (func_def->func_id == func_id) {
|
||||
int i, obj_arg_num = 0, ptr_arg_num = 0;
|
||||
intptr_t argv_copy_buf[16];
|
||||
intptr_t *argv_copy = argv_copy_buf;
|
||||
|
||||
if (func_def->arg_num > 16) {
|
||||
argv_copy = (intptr_t *)bh_malloc(func_def->arg_num *
|
||||
sizeof(intptr_t));
|
||||
if (argv_copy == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init argv_copy */
|
||||
for (i = 0; i < func_def->arg_num; i++)
|
||||
argv_copy[i] = (intptr_t)argv[i];
|
||||
|
||||
/* Validate object arguments */
|
||||
i = 0;
|
||||
for (; i < OBJ_ARG_NUM_MAX && func_def->obj_arg_indexes[i] != 0xff;
|
||||
i++, obj_arg_num++) {
|
||||
uint8 index = func_def->obj_arg_indexes[i];
|
||||
bool null_ok = index & NULL_OK;
|
||||
|
||||
index = index & (~NULL_OK);
|
||||
|
||||
/* Some API's allow to pass NULL obj, such as xxx_create() */
|
||||
if (argv[index] == 0) {
|
||||
if (!null_ok) {
|
||||
THROW_EXC("the object id is 0 and invalid");
|
||||
goto fail;
|
||||
}
|
||||
/* Continue so that to pass null object validation */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!wgl_native_validate_object(argv[index], (lv_obj_t **)&argv_copy[index])) {
|
||||
THROW_EXC("the object is invalid");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate address arguments */
|
||||
i = 0;
|
||||
for (; i < PTR_ARG_NUM_MAX && func_def->ptr_arg_indexes[i] != 0xff;
|
||||
i++, ptr_arg_num++) {
|
||||
uint8 index = func_def->ptr_arg_indexes[i];
|
||||
|
||||
/* The index+1 arg is the data size to be validated */
|
||||
if (!validate_app_addr(argv[index], argv[index + 1]))
|
||||
goto fail;
|
||||
|
||||
/* Convert to native address before call lvgl function */
|
||||
argv_copy[index] = (intptr_t)addr_app_to_native(argv[index]);
|
||||
}
|
||||
|
||||
if (func_def->has_ret == NO_RET)
|
||||
invokeNative_Void(argv_copy,
|
||||
func_def->arg_num,
|
||||
func_def->func_ptr);
|
||||
else
|
||||
argv[0] = invokeNative_Int32(argv_copy,
|
||||
func_def->arg_num,
|
||||
func_def->func_ptr);
|
||||
|
||||
if (argv_copy != argv_copy_buf)
|
||||
bh_free(argv_copy);
|
||||
|
||||
/* success return */
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (argv_copy != argv_copy_buf)
|
||||
bh_free(argv_copy);
|
||||
return;
|
||||
}
|
||||
|
||||
func_def++;
|
||||
}
|
||||
|
||||
THROW_EXC("the native widget function is not found!");
|
||||
}
|
||||
|
||||
73
core/iwasm/lib/native/extension/gui/wgl_native_utils.h
Normal file
73
core/iwasm/lib/native/extension/gui/wgl_native_utils.h
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
|
||||
#ifndef WAMR_GRAPHIC_LIBRARY_NATIVE_UTILS_H
|
||||
#define WAMR_GRAPHIC_LIBRARY_NATIVE_UTILS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "bh_platform.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
#define OBJ_ARG_NUM_MAX 4
|
||||
#define PTR_ARG_NUM_MAX 4
|
||||
|
||||
#define NULL_OK 0x80
|
||||
|
||||
enum {
|
||||
HAS_RET,
|
||||
NO_RET
|
||||
};
|
||||
|
||||
enum {
|
||||
WIDGET_TYPE_BTN,
|
||||
WIDGET_TYPE_LABEL,
|
||||
WIDGET_TYPE_CB,
|
||||
WIDGET_TYPE_LIST,
|
||||
WIDGET_TYPE_DDLIST,
|
||||
|
||||
_WIDGET_TYPE_NUM,
|
||||
};
|
||||
|
||||
typedef struct WGLNativeFuncDef {
|
||||
/* Function id */
|
||||
int32 func_id;
|
||||
|
||||
/* Native function pointer */
|
||||
void *func_ptr;
|
||||
|
||||
/* whether has return value */
|
||||
uint8 has_ret;
|
||||
|
||||
/* argument number */
|
||||
uint8 arg_num;
|
||||
|
||||
/* low 7 bit: obj argument index
|
||||
* highest 1 bit: allow obj be null or not
|
||||
* -1 means the end of this array */
|
||||
uint8 obj_arg_indexes[OBJ_ARG_NUM_MAX];
|
||||
|
||||
/* pointer argument indexes, -1 means the end of this array */
|
||||
uint8 ptr_arg_indexes[PTR_ARG_NUM_MAX];
|
||||
} WGLNativeFuncDef;
|
||||
|
||||
bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj);
|
||||
|
||||
bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id);
|
||||
|
||||
uint32 wgl_native_wigdet_create(int8 widget_type,
|
||||
lv_obj_t *par,
|
||||
lv_obj_t *copy);
|
||||
|
||||
void wgl_native_func_call(WGLNativeFuncDef *funcs,
|
||||
uint32 size,
|
||||
int32 func_id,
|
||||
uint32 argv_offset,
|
||||
uint32 argc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WAMR_GRAPHIC_LIBRARY_NATIVE_UTILS_H */
|
||||
353
core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c
Normal file
353
core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "app_manager_export.h"
|
||||
#include "module_wasm_app.h"
|
||||
#include "bh_list.h"
|
||||
#include "bh_thread.h"
|
||||
#include "wgl_native_utils.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
bh_list_link l;
|
||||
|
||||
/* The object id. */
|
||||
uint32 obj_id;
|
||||
|
||||
/* The lv object */
|
||||
lv_obj_t *obj;
|
||||
|
||||
/* Module id that the obj belongs to */
|
||||
uint32 module_id;
|
||||
} object_node_t;
|
||||
|
||||
typedef struct {
|
||||
int32 obj_id;
|
||||
lv_event_t event;
|
||||
} object_event_t;
|
||||
|
||||
/* Max obj id */
|
||||
static uint32 g_obj_id_max = 0;
|
||||
|
||||
static bh_list g_object_list;
|
||||
|
||||
static korp_mutex g_object_list_mutex;
|
||||
|
||||
static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg)
|
||||
{
|
||||
uint32 argv[2];
|
||||
wasm_function_inst_t func_on_object_event;
|
||||
bh_assert(WIDGET_EVENT_WASM == bh_message_type(msg));
|
||||
wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data;
|
||||
wasm_module_inst_t inst = wasm_app_data->wasm_module_inst;
|
||||
object_event_t *object_event
|
||||
= (object_event_t *)bh_message_payload(msg);
|
||||
|
||||
if (object_event == NULL)
|
||||
return;
|
||||
|
||||
func_on_object_event = wasm_runtime_lookup_function(inst, "_on_widget_event",
|
||||
"(i32i32)");
|
||||
if (!func_on_object_event) {
|
||||
printf("Cannot find function _on_object_event\n");
|
||||
return;
|
||||
}
|
||||
|
||||
argv[0] = object_event->obj_id;
|
||||
argv[1] = object_event->event;
|
||||
if (!wasm_runtime_call_wasm(inst, NULL, func_on_object_event, 2, argv)) {
|
||||
printf(":Got exception running wasm code: %s\n",
|
||||
wasm_runtime_get_exception(inst));
|
||||
wasm_runtime_clear_exception(inst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup_object_list(uint32 module_id)
|
||||
{
|
||||
object_node_t *elem;
|
||||
|
||||
vm_mutex_lock(&g_object_list_mutex);
|
||||
|
||||
while (true) {
|
||||
bool found = false;
|
||||
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
|
||||
while (elem) {
|
||||
/* delete the leaf node belongs to the module firstly */
|
||||
if (module_id == elem->module_id &&
|
||||
lv_obj_count_children(elem->obj) == 0) {
|
||||
object_node_t *next = (object_node_t *)bh_list_elem_next(elem);
|
||||
|
||||
found = true;
|
||||
lv_obj_del(elem->obj);
|
||||
bh_list_remove(&g_object_list, elem);
|
||||
bh_free(elem);
|
||||
elem = next;
|
||||
} else {
|
||||
elem = (object_node_t *)bh_list_elem_next(elem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
break;
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
}
|
||||
|
||||
static bool init_object_event_callback_framework()
|
||||
{
|
||||
if (!wasm_register_cleanup_callback(cleanup_object_list)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!wasm_register_msg_callback(WIDGET_EVENT_WASM,
|
||||
app_mgr_object_event_callback)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wgl_native_validate_object(int32 obj_id, lv_obj_t **obj)
|
||||
{
|
||||
object_node_t *elem;
|
||||
|
||||
vm_mutex_lock(&g_object_list_mutex);
|
||||
|
||||
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
|
||||
while (elem) {
|
||||
if (obj_id == elem->obj_id) {
|
||||
if (obj != NULL)
|
||||
*obj = elem->obj;
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
return true;
|
||||
}
|
||||
elem = (object_node_t *) bh_list_elem_next(elem);
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wgl_native_add_object(lv_obj_t *obj, uint32 module_id, uint32 *obj_id)
|
||||
{
|
||||
object_node_t *node;
|
||||
|
||||
node = (object_node_t *) bh_malloc(sizeof(object_node_t));
|
||||
|
||||
if (node == NULL)
|
||||
return false;
|
||||
|
||||
/* Generate an obj id */
|
||||
g_obj_id_max++;
|
||||
if (g_obj_id_max == -1)
|
||||
g_obj_id_max = 1;
|
||||
|
||||
memset(node, 0, sizeof(*node));
|
||||
node->obj = obj;
|
||||
node->obj_id = g_obj_id_max;
|
||||
node->module_id = module_id;
|
||||
|
||||
vm_mutex_lock(&g_object_list_mutex);
|
||||
bh_list_insert(&g_object_list, node);
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
|
||||
if (obj_id != NULL)
|
||||
*obj_id = node->obj_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _obj_del_recursive(lv_obj_t *obj)
|
||||
{
|
||||
object_node_t *elem;
|
||||
lv_obj_t * i;
|
||||
lv_obj_t * i_next;
|
||||
|
||||
i = lv_ll_get_head(&(obj->child_ll));
|
||||
|
||||
while (i != NULL) {
|
||||
/*Get the next object before delete this*/
|
||||
i_next = lv_ll_get_next(&(obj->child_ll), i);
|
||||
|
||||
/*Call the recursive del to the child too*/
|
||||
_obj_del_recursive(i);
|
||||
|
||||
/*Set i to the next node*/
|
||||
i = i_next;
|
||||
}
|
||||
|
||||
vm_mutex_lock(&g_object_list_mutex);
|
||||
|
||||
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
|
||||
while (elem) {
|
||||
if (obj == elem->obj) {
|
||||
bh_list_remove(&g_object_list, elem);
|
||||
bh_free(elem);
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
return;
|
||||
}
|
||||
elem = (object_node_t *) bh_list_elem_next(elem);
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
}
|
||||
|
||||
static void _obj_clean_recursive(lv_obj_t *obj)
|
||||
{
|
||||
lv_obj_t * i;
|
||||
lv_obj_t * i_next;
|
||||
|
||||
i = lv_ll_get_head(&(obj->child_ll));
|
||||
|
||||
while (i != NULL) {
|
||||
/*Get the next object before delete this*/
|
||||
i_next = lv_ll_get_next(&(obj->child_ll), i);
|
||||
|
||||
/*Call the recursive del to the child too*/
|
||||
_obj_del_recursive(i);
|
||||
|
||||
/*Set i to the next node*/
|
||||
i = i_next;
|
||||
}
|
||||
}
|
||||
|
||||
static void post_widget_msg_to_module(object_node_t *object_node, lv_event_t event)
|
||||
{
|
||||
module_data *module = module_data_list_lookup_id(object_node->module_id);
|
||||
object_event_t *object_event;
|
||||
|
||||
if (module == NULL)
|
||||
return;
|
||||
|
||||
object_event = (object_event_t *)bh_malloc(sizeof(*object_event));
|
||||
if (object_event == NULL)
|
||||
return;
|
||||
|
||||
memset(object_event, 0, sizeof(*object_event));
|
||||
object_event->obj_id = object_node->obj_id;
|
||||
object_event->event = event;
|
||||
|
||||
bh_post_msg(module->queue,
|
||||
WIDGET_EVENT_WASM,
|
||||
object_event,
|
||||
sizeof(*object_event));
|
||||
}
|
||||
|
||||
static void internal_lv_obj_event_cb(lv_obj_t *obj, lv_event_t event)
|
||||
{
|
||||
object_node_t *elem;
|
||||
|
||||
vm_mutex_lock(&g_object_list_mutex);
|
||||
|
||||
elem = (object_node_t *)bh_list_first_elem(&g_object_list);
|
||||
while (elem) {
|
||||
if (obj == elem->obj) {
|
||||
post_widget_msg_to_module(elem, event);
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
return;
|
||||
}
|
||||
elem = (object_node_t *) bh_list_elem_next(elem);
|
||||
}
|
||||
|
||||
vm_mutex_unlock(&g_object_list_mutex);
|
||||
}
|
||||
|
||||
static void* lv_task_handler_thread_routine (void *arg)
|
||||
{
|
||||
korp_sem sem;
|
||||
|
||||
vm_sem_init(&sem, 0);
|
||||
|
||||
while (true) {
|
||||
vm_sem_reltimedwait(&sem, 100);
|
||||
lv_task_handler();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void wgl_init(void)
|
||||
{
|
||||
korp_thread tid;
|
||||
|
||||
lv_init();
|
||||
|
||||
bh_list_init(&g_object_list);
|
||||
vm_recursive_mutex_init(&g_object_list_mutex);
|
||||
init_object_event_callback_framework();
|
||||
|
||||
/* new a thread, call lv_task_handler periodically */
|
||||
vm_thread_create(&tid,
|
||||
lv_task_handler_thread_routine,
|
||||
NULL,
|
||||
BH_APPLET_PRESERVED_STACK_SIZE);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* Obj native function wrappers
|
||||
* -------------------------------------------------------------------------*/
|
||||
static lv_res_t _obj_del(lv_obj_t *obj)
|
||||
{
|
||||
/* Recursively delete object node in the list belong to this
|
||||
* parent object including itself */
|
||||
_obj_del_recursive(obj);
|
||||
|
||||
return lv_obj_del(obj);
|
||||
}
|
||||
|
||||
static void _obj_clean(lv_obj_t *obj)
|
||||
{
|
||||
/* Recursively delete child object node in the list belong to this
|
||||
* parent object */
|
||||
_obj_clean_recursive(obj);
|
||||
|
||||
/* Delete all of its children */
|
||||
lv_obj_clean(obj);
|
||||
}
|
||||
|
||||
static void _obj_set_event_cb(lv_obj_t *obj)
|
||||
{
|
||||
lv_obj_set_event_cb(obj, internal_lv_obj_event_cb);
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static WGLNativeFuncDef obj_native_func_defs[] = {
|
||||
{ OBJ_FUNC_ID_DEL, _obj_del, HAS_RET, 1, {0, -1}, {-1} },
|
||||
{ OBJ_FUNC_ID_DEL_ASYNC, lv_obj_del_async, NO_RET, 1, {0, -1}, {-1} },
|
||||
{ OBJ_FUNC_ID_CLEAN, _obj_clean, NO_RET, 1, {0, -1}, {-1} },
|
||||
{ OBJ_FUNC_ID_ALIGN, lv_obj_align, NO_RET, 5, {0, 1 | NULL_OK, -1}, {-1} },
|
||||
{ OBJ_FUNC_ID_SET_EVT_CB, _obj_set_event_cb, NO_RET, 1, {0, -1}, {-1} },
|
||||
};
|
||||
|
||||
/*************** Native Interface to Wasm App ***********/
|
||||
void wasm_obj_native_call(int32 func_id, uint32 argv_offset, uint32 argc)
|
||||
{
|
||||
uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef);
|
||||
|
||||
wgl_native_func_call(obj_native_func_defs,
|
||||
size,
|
||||
func_id,
|
||||
argv_offset,
|
||||
argc);
|
||||
}
|
||||
Reference in New Issue
Block a user