使用Native、XComponent和EGL绘制图形

使用Native、XComponent和EGL绘制图形

HarmonyOS
2024-05-21 21:51:15
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
pumayze

本demo实现了绘制矩形的功能,可以通过触摸矩形区域为矩形更换颜色,点击绘制矩形按钮后恢复原本的颜色。

核心组件

EGL(Embedded    Graphic Library):EGL 是Khronos渲染API (如OpenGL ES 或 OpenVG) 与底层原生窗口系统之间的接口。

XComponent:可用于EGL/OpenGLES和媒体数据写入,并显示在XComponent组件。

项目代码结构

├──entry/src/main

│ ├──cpp // C++代码区

│ │ ├──CMakeLists.txt // CMake配置文件

│ │ ├──hello.cpp // C++源代码

│ │ ├──common

│ │ │ └──common.h // 常量定义文件

│ │ ├──manager // 生命周期管理模块

│ │ │ ├──PluginManager.cpp

│ │ │ └──PluginManager.h

│ │ ├──render // 渲染模块

│ │ │ ├──EGLCore.cpp

│ │ │ ├──EGLCore.h

│ │ │ ├──PluginRender.cpp

│ │ │ └──PluginRender.h

│ │ └──types // 接口存放文件夹

│ │ └──libentry

│ │ ├──index.d.ts // 接口文件

│ │ └──oh-package.json5 // 接口注册配置文件

│ └──ets // 代码区

│ ├──common

│ │ └──CommonConstants.ets // 常量定义文件

│ ├──entryability

│ │ └──EntryAbility.ts // 程序入口类

│ └──pages // 页面文件

│ └──Index.ets // 主界面

└──entry/src/main/resources // 资源文件目录

demo架构

使用C++代码实现业务逻辑,ArkTS代码用于前端界面以及调用相关方法

C++侧:实现图像渲染、应用管理以及页面的生命周期管理

ArkTS侧:调用c++侧的图形渲染方法以及生命周期管理方法,实现前端界面

CMake:跨平台编译工具,将C++代码编译成so文件提供给ArkTS

ArkTS代码

定义XComponent

XComponent({ 
  // 定义XComponent 
  id: CommonConstants.XCOMPONENT_ID, 
  type: CommonConstants.XCOMPONENT_TYPE, 
  libraryname: CommonConstants.XCOMPONENT_LIBRARY_NAME 
}) 
  .onLoad((xComponentContext?: object | Record<string, () => void>) => { 
    if (xComponentContext){ 
      this.xComponentContext = xComponentContext as Record<string, () => void>; 
    } 
  })

ArkTS核心代码

// 导入C++侧实现的方法 
import entry from 'libentry.so' 
 
@Entry 
@Component 
struct Index { 
  // XComponent实例对象的context 
  private xComponentContext: Record<string, () => void> = {}; 
 
  // ... 生命周期相关 
 
 
  build() { 
    Column() { 
      // 标题 
      Row() { 
        Text($r('app.string.title')) 
          .fontSize($r('app.float.title_text_font_size')) 
          .fontWeight(CommonConstants.FONT_WEIGHT) 
          .margin( 
            { 
              left: $r('app.float.title_text_margin_left'), 
              top: $r('app.float.title_text_margin_top') 
            } 
          ) 
      } 
      .margin({ top: $r('app.float.title_margin_top') }) 
      .width(CommonConstants.FULL_PARENT) 
      .height($r('app.float.title_height')) 
 
      Column() { 
        // 增加XComponent组件 
        XComponent({ 
          // 定义XComponent 
          id: CommonConstants.XCOMPONENT_ID, 
          type: CommonConstants.XCOMPONENT_TYPE, 
          libraryname: CommonConstants.XCOMPONENT_LIBRARY_NAME 
        }) 
          .onLoad((xComponentContext?: object | Record<string, () => void>) => { 
            if (xComponentContext){ 
              this.xComponentContext = xComponentContext as Record<string, () => void>; 
            } 
          }) 
      } 
      .margin({ 
        top: $r('app.float.xcomponent_margin_top'), 
        left: $r('app.float.xcomponent_margin_left'), 
        right: $r('app.float.xcomponent_margin_right') 
      }) 
      .height(CommonConstants.XCOMPONENT_HEIGHT) 
 
      Row() { 
        // button组件 
        Button($r('app.string.button_text')) 
          .fontSize($r('app.float.button_font_size')) 
          .fontWeight(CommonConstants.FONT_WEIGHT) 
          .margin({ bottom: $r('app.float.button_margin_bottom') }) 
          .onClick(() => { 
            if (this.xComponentContext) { 
              // 点击button便重新绘制 
              this.xComponentContext.drawRectangle(); 
            } 
          }) 
          .width(CommonConstants.BUTTON_WIDTH) 
          .height($r('app.float.button_height')) 
      } 
      .width(CommonConstants.FULL_PARENT) 
      .justifyContent(FlexAlign.Center) 
      .alignItems(VerticalAlign.Bottom) 
      .layoutWeight(CommonConstants.LAYOUT_WEIGHT) 
    } 
    .width(CommonConstants.FULL_PARENT) 
    .height(CommonConstants.FULL_PARENT) 
  } 
}

界面

C++代码

模块注册 hello.cpp

EXTERN_C_START 
static napi_value Init(napi_env env, napi_value exports) 
{ 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Init", "Init begins"); 
  if ((nullptr == env) || (nullptr == exports)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "env or exports is null"); 
    return nullptr; 
  } 
  // 暴露接口getContext() 
  napi_property_descriptor desc[] = { 
  { "getContext", nullptr, PluginManager::GetContext, nullptr, nullptr, nullptr, napi_default, nullptr } 
}; 
if (napi_ok != napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)) { 
  OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Init", "napi_define_properties failed"); 
  return nullptr; 
} 
// 方法内检查环境变量是否包含XComponent组件实例,若实例存在注册绘制相关接口 
PluginManager::GetInstance()->Export(env, exports); 
return exports; 
} 
EXTERN_C_END 
 
static napi_module demoModule = { 
  .nm_version = 1, 
  .nm_flags = 0, 
  .nm_filename = nullptr, 
  // 入口函数 
  .nm_register_func = Init, 
  // 模块名称 
  .nm_modname = "entry", 
  .nm_priv = ((void*)0), 
  .reserved = { 0 }, 
}; 
 
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) 
{ 
  napi_module_register(&demoModule); 
}

注册XComponent事件回调

定义surface创建、改变、销毁和XComponent触摸事件回调

// 定义一个函数OnSurfaceCreatedCB(),封装初始化环境与绘制背景 
void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB"); 
  if ((nullptr == component) || (nullptr == window)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceCreatedCB: component or window is null"); 
    return; 
  } 
 
  // 获取XComponent的id,即JS侧XComponent组件构造中的id参数 
  char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; 
  uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 
  if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceCreatedCB: Unable to get XComponent id"); 
    return; 
  } 
 
  // 初始化环境与绘制背景 
  std::string id(idStr); 
  auto render = PluginRender::GetInstance(id); 
  uint64_t width; 
  uint64_t height; 
  // 获取XComponent拥有的surface的大小 
  int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height); 
  if ((OH_NATIVEXCOMPONENT_RESULT_SUCCESS == xSize) && (nullptr != render)) { 
    if (render->m_eglCore->EglContextInit(window, width, height)) { 
      render->m_eglCore->Background(); 
    } 
  } 
} 
 
// 定义一个函数OnSurfaceChangedCB(),surface改变 
void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceChangedCB"); 
  if ((nullptr == component) || (nullptr == window)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceChangedCB: component or window is null"); 
    return; 
  } 
 
  // 获取XComponent的id 
  char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; 
  uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 
  if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceChangedCB: Unable to get XComponent id"); 
    return; 
  } 
 
  std::string id(idStr); 
  auto render = PluginRender::GetInstance(id); 
  if (nullptr != render) { 
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "surface changed"); 
  } 
} 
 
// 定义一个函数OnSurfaceDestroyedCB(),将PluginRender类内释放资源的方法Release()封装在其中 
void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB"); 
  if ((nullptr == component) || (nullptr == window)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceDestroyedCB: component or window is null"); 
    return; 
  } 
 
  char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; 
  uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 
  if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "OnSurfaceDestroyedCB: Unable to get XComponent id"); 
    return; 
  } 
 
  std::string id(idStr); 
  PluginRender::Release(id); 
} 
 
// 定义一个函数DispatchTouchEventCB(),响应触摸事件时触发该回调 
void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB"); 
  if ((nullptr == component) || (nullptr == window)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "DispatchTouchEventCB: component or window is null"); 
    return; 
  } 
 
  char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; 
  uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 
  if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(component, idStr, &idSize)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", 
      "DispatchTouchEventCB: Unable to get XComponent id"); 
    return; 
  } 
 
  std::string id(idStr); 
  PluginRender *render = PluginRender::GetInstance(id); 
  if (nullptr != render) { 
    render->m_eglCore->ChangeColor(); 
  } 
}

矩形绘制方法

napi_value PluginRender::NapiDrawRectangle(napi_env env, napi_callback_info info) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle"); 
  if ((nullptr == env) || (nullptr == info)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: env or info is null"); 
    return nullptr; 
  } 
 
  // 获取环境变量参数 
  napi_value thisArg; 
  if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: napi_get_cb_info fail"); 
    return nullptr; 
  } 
 
  // 获取环境变量中XComponent实例 
  napi_value exportInstance; 
  if (napi_ok != napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", 
      "NapiDrawRectangle: napi_get_named_property fail"); 
    return nullptr; 
  } 
 
  // 通过napi_unwrap接口,获取XComponent的实例指针 
  OH_NativeXComponent *nativeXComponent = nullptr; 
  if (napi_ok != napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: napi_unwrap fail"); 
    return nullptr; 
  } 
 
  // 获取XComponent实例的id 
  char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'}; 
  uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1; 
  if (OH_NATIVEXCOMPONENT_RESULT_SUCCESS != OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", 
      "NapiDrawRectangle: Unable to get XComponent id"); 
    return nullptr; 
  } 
 
  std::string id(idStr); 
  PluginRender *render = PluginRender::GetInstance(id); 
  if (render) { 
    // 绘制 
    render->m_eglCore->Draw(); 
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->m_eglCore->Draw() executed"); 
  } 
  return nullptr; 
}

初始化EGL

bool EGLCore::EglContextInit(void *window, int width, int height) { 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute"); 
  if ((nullptr == window) || (0 >= width) || (0 >= height)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error"); 
    return false; 
  } 
 
  m_width = width; 
  m_height = height; 
  if (0 < m_width) { 
    m_widthPercent = FIFTY_PERCENT * m_height / m_width; 
  } 
  m_eglWindow = reinterpret_cast<EGLNativeWindowType>(window); 
 
  // 初始化display 
  m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 
  if (EGL_NO_DISPLAY == m_eglDisplay) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display"); 
    return false; 
  } 
 
  // 初始化EGL 
  EGLint majorVersion; 
  EGLint minorVersion; 
  if (!eglInitialize(m_eglDisplay, &majorVersion, &minorVersion)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", 
      "eglInitialize: unable to get initialize EGL display"); 
    return false; 
  } 
 
  // 选择配置 
  const EGLint maxConfigSize = 1; 
  EGLint numConfigs; 
  if (!eglChooseConfig(m_eglDisplay, ATTRIB_LIST, &m_eglConfig, maxConfigSize, &numConfigs)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs"); 
    return false; 
  } 
 
  // 创建环境 
  return CreateEnvironment(); 
} 
 
bool EGLCore::CreateEnvironment() { 
  // 创建surface. 
  if (!m_eglWindow) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "m_eglWindow is null"); 
    return false; 
  } 
  m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_eglWindow, NULL); 
 
  if (nullptr == m_eglSurface) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", 
      "eglCreateWindowSurface: unable to create surface"); 
    return false; 
  } 
 
  // 创建context. 
  m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, CONTEXT_ATTRIBS); 
  if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed"); 
    return false; 
  } 
 
  // 创建program. 
  m_program = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER); 
  if (PROGRAM_ERROR == m_program) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program"); 
    return false; 
  } 
  return true; 
}

渲染实现

绘制背景

// 绘制背景颜色 
const GLfloat BACKGROUND_COLOR[] = { 24.0f / 255, 36.0f / 255, 49.0f / 255, 1.0f }; 
 
// 绘制背景顶点 
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = { 
  -1.0f, 1.0f, 
  1.0f, 1.0f, 
  1.0f, -1.0f, 
  -1.0f, -1.0f 
}; 
 
 
// 绘制背景 
void EGLCore::Background() { 
  GLint position = PrepareDraw(); // 绘制前准备,获取position值,若创建成功,position从0开始 
  if (POSITION_ERROR == position) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed"); 
    return; 
  } 
 
  // 依据传入参数在指定区域绘制指定颜色 
  if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 
    sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed"); 
    return; 
  } 
 
  // 结束绘制操作 
  if (!FinishDraw()) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed"); 
    return; 
  } 
}

绘制图形

void EGLCore::Draw() { 
  m_flag = false; 
  OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw"); 
  GLint position = PrepareDraw(); 
  if (POSITION_ERROR == position) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed"); 
    return; 
  } 
 
  if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 
    sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed"); 
    return; 
  } 
 
  const GLfloat rectangleVertices[] = {-m_widthPercent, FIFTY_PERCENT,  m_widthPercent,  FIFTY_PERCENT, 
    m_widthPercent,  -FIFTY_PERCENT, -m_widthPercent, -FIFTY_PERCENT}; 
  if (!ExecuteDraw(position, DRAW_COLOR, rectangleVertices, sizeof(rectangleVertices))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw rectangle failed"); 
    return; 
  } 
 
  if (!FinishDraw()) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); 
    return; 
  } 
 
  m_flag = true; 
}

改变颜色,重新绘制大小相同颜色不同的图形

void EGLCore::ChangeColor() { 
  if (!m_flag) { 
    return; 
  } 
 
  GLint position = PrepareDraw(); 
  if (POSITION_ERROR == position) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed"); 
    return; 
  } 
 
  if (!ExecuteDraw(position, BACKGROUND_COLOR, BACKGROUND_RECTANGLE_VERTICES, 
    sizeof(BACKGROUND_RECTANGLE_VERTICES))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed"); 
    return; 
  } 
 
  const GLfloat rectangleVertices[] = {-m_widthPercent, FIFTY_PERCENT,  m_widthPercent,  FIFTY_PERCENT, 
    m_widthPercent,  -FIFTY_PERCENT, -m_widthPercent, -FIFTY_PERCENT}; 
  if (!ExecuteDraw(position, CHANGE_COLOR, rectangleVertices, sizeof(rectangleVertices))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw rectangle failed"); 
    return; 
  } 
 
  if (!FinishDraw()) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed"); 
  } 
}

资源释放

EGLCore的资源释放

void EGLCore::Release() { 
  // 释放surface 
  if ((nullptr == m_eglDisplay) || (nullptr == m_eglSurface) || (!eglDestroySurface(m_eglDisplay, m_eglSurface))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed"); 
  } 
 
  // 释放context 
  if ((nullptr == m_eglDisplay) || (nullptr == m_eglContext) || (!eglDestroyContext(m_eglDisplay, m_eglContext))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed"); 
  } 
 
  // 释放display 
  if ((nullptr == m_eglDisplay) || (!eglTerminate(m_eglDisplay))) { 
    OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed"); 
  } 
}

PluginRender的资源释放

void PluginRender::Release(std::string &id) { 
  PluginRender *render = PluginRender::GetInstance(id); 
  if (nullptr != render) { 
    render->m_eglCore->Release(); 
    delete render->m_eglCore; 
    render->m_eglCore = nullptr; 
    delete render; 
    render = nullptr; 
    m_instance.erase(m_instance.find(id)); 
  } 
}

CMakeLists,编译成动态链接库

# the minimum version of CMake. 
cmake_minimum_required(VERSION 3.4.1) 
project(xcomponent) 
 
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) 
 
include_directories(${NATIVERENDER_ROOT_PATH} 
${NATIVERENDER_ROOT_PATH}/include) 
 
add_library(entry SHARED 
render/EGLCore.cpp 
render/PluginRender.cpp 
manager/PluginManager.cpp 
hello.cpp 
) 
 
find_library( 
  EGL-lib 
EGL 
) 
 
find_library( 
  GLES-lib 
GLESv3 
) 
 
find_library( 
  hilog-lib 
hilog_ndk.z 
) 
 
find_library( 
  libace-lib 
ace_ndk.z 
) 
 
find_library( 
  libnapi-lib 
ace_napi.z 
) 
 
find_library( 
  libuv-lib 
uv 
) 
 
target_link_libraries(entry PUBLIC 
${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib} libc++.a libace_napi.z.so)

效果展示

绘制矩形

触摸矩形改变颜色

分享
微博
QQ
微信
回复
2024-05-22 17:07:35
相关问题
画布上绘制图片如何实现?
247浏览 • 1回复 待解决
HarmonyOS Canvas中关于绘制图片问题
209浏览 • 1回复 待解决
XComponent、NativeDrawing实现2D图形绘制
976浏览 • 1回复 待解决
XComponent、openGL实现3D图形绘制
1397浏览 • 1回复 待解决
使用Drawing实现图形绘制与显示
770浏览 • 1回复 待解决
XComponent是怎么与native进行关联的?
2535浏览 • 1回复 待解决
通过Native 调用c++层实现文本绘制
883浏览 • 1回复 待解决
XComponent使用OpenGl ES
960浏览 • 1回复 待解决
多线程中EGL如何共享Context
300浏览 • 1回复 待解决
图形图像开发场景实践
621浏览 • 1回复 待解决
关于初始化EGL环境相关问题
457浏览 • 1回复 待解决
如何使用canvas绘制圆角矩形
392浏览 • 1回复 待解决
native使用fork函数,出现cppcrash
1580浏览 • 1回复 待解决