鸿蒙(API 12 Beta6版)图形【NativeImage开发指导 (C/C++)】方舟2D图形服务

场景介绍

NativeImage是提供Surface关联OpenGL外部纹理的模块,表示图形队列的消费者端。开发者可以通过NativeImage接口接收和使用Buffer,并将Buffer关联输出到OpenGL外部纹理。

针对NativeImage,常见的开发场景如下:

  • 通过NativeImage提供的Native API接口创建NativeImage实例作为消费者端,获取与该实例对应的NativeWindow作为生产者端。NativeWindow相关接口可用于填充Buffer内容并提交,NativeImage将Buffer内容更新到OpenGL外部纹理上。本模块需要配合NativeWindow、NativeBuffer、EGL、GLES3模块一起使用。

接口说明

接口名描述
OH_NativeImage_Create (uint32_t textureId, uint32_t textureTarget)创建一个OH_NativeImage实例,该实例与OpenGL ES的纹理ID和纹理目标相关联。
OH_NativeImage_AcquireNativeWindow (OH_NativeImage *image)获取与OH_NativeImage相关联的OHNativeWindow指针,该OHNativeWindow后续不再需要时需要调用 OH_NativeWindow_DestroyNativeWindow释放。
OH_NativeImage_AttachContext (OH_NativeImage *image, uint32_t textureId)将OH_NativeImage实例附加到当前OpenGL ES上下文,且该OpenGL ES纹理会绑定到 GL_TEXTURE_EXTERNAL_OES,并通过OH_NativeImage进行更新。
OH_NativeImage_DetachContext (OH_NativeImage *image)将OH_NativeImage实例从当前OpenGL ES上下文分离。
OH_NativeImage_UpdateSurfaceImage (OH_NativeImage *image)通过OH_NativeImage获取最新帧更新相关联的OpenGL ES纹理。
OH_NativeImage_GetTimestamp (OH_NativeImage *image)获取最近调用OH_NativeImage_UpdateSurfaceImage的纹理图像的相关时间戳。
OH_NativeImage_GetTransformMatrix (OH_NativeImage *image, float matrix[16])获取最近调用OH_NativeImage_UpdateSurfaceImage的纹理图像的变化矩阵。
OH_NativeImage_Destroy (OH_NativeImage **image)销毁通过OH_NativeImage_Create创建的OH_NativeImage实例,销毁后该OH_NativeImage指针会被赋值为空。

开发步骤

以下步骤描述了如何使用NativeImage提供的Native API接口,创建OH_NativeImage实例作为消费者端,将数据内容更新到OpenGL外部纹理上。

添加动态链接库

CMakeLists.txt中添加以下lib。

libEGL.so
libGLESv3.so
libnative_image.so
libnative_window.so
libnative_buffer.so

头文件

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <native_image/native_image.h>
#include <native_window/external_window.h>
#include <native_buffer/native_buffer.h>
  1. 初始化EGL环境

这里提供一份初始化EGL环境的代码示例。

#include <iostream>
#include <string>
#include <EGL/egl.h>
#include <EGL/eglext.h>using GetPlatformDisplayExt = PFNEGLGETPLATFORMDISPLAYEXTPROC;
constexpr const char *EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland";
constexpr const char *EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland";
constexpr int32_t EGL_CONTEXT_CLIENT_VERSION_NUM = 2;
constexpr char CHARACTER_WHITESPACE = ' ';
constexpr const char *CHARACTER_STRING_WHITESPACE = " ";
constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT";
EGLContext eglContext_ = EGL_NO_CONTEXT;
EGLDisplay eglDisplay_ = EGL_NO_DISPLAY;
static inline EGLConfig config_;
static inline EGLSurface eglsurface_;
// 从XComponent中获取到的OHNativeWindow
OHNativeWindow *eglNativeWindow_;// 检查egl扩展
static bool CheckEglExtension(const char *extensions, const char *extension) {size_t extlen = strlen(extension);const char *end = extensions + strlen(extensions);while (extensions < end) {size_t n = 0;if (*extensions == CHARACTER_WHITESPACE) {extensions++;continue;}n = strcspn(extensions, CHARACTER_STRING_WHITESPACE);if (n == extlen && strncmp(extension, extensions, n) == 0) {return true;}extensions += n;}return false;
}// 获取当前的显示设备
static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void *native_display, const EGLint *attrib_list) {static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL;if (!eglGetPlatformDisplayExt) {const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);if (extensions && (CheckEglExtension(extensions, EGL_EXT_PLATFORM_WAYLAND) ||CheckEglExtension(extensions, EGL_KHR_PLATFORM_WAYLAND))) {eglGetPlatformDisplayExt = (GetPlatformDisplayExt)eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT);}}if (eglGetPlatformDisplayExt) {return eglGetPlatformDisplayExt(platform, native_display, attrib_list);}return eglGetDisplay((EGLNativeDisplayType)native_display);
}static void InitEGLEnv() {// 获取当前的显示设备eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL);if (eglDisplay_ == EGL_NO_DISPLAY) {std::cout << "Failed to create EGLDisplay gl errno : " << eglGetError() << std::endl;}EGLint major, minor;// 初始化EGLDisplayif (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {std::cout << "Failed to initialize EGLDisplay" << std::endl;}// 绑定图形绘制的API为OpenGLESif (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {std::cout << "Failed to bind OpenGL ES API" << std::endl;}unsigned int ret;EGLint count;EGLint config_attribs[] = {EGL_SURFACE_TYPE,EGL_WINDOW_BIT,EGL_RED_SIZE,8,EGL_GREEN_SIZE,8,EGL_BLUE_SIZE,8,EGL_ALPHA_SIZE,8,EGL_RENDERABLE_TYPE,EGL_OPENGL_ES3_BIT,EGL_NONE};// 获取一个有效的系统配置信息ret = eglChooseConfig(eglDisplay_, config_attribs, &config_, 1, &count);if (!(ret && static_cast<unsigned int>(count) >= 1)) {std::cout << "Failed to eglChooseConfig" << std::endl;}static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE};// 创建上下文eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, context_attribs);if (eglContext_ == EGL_NO_CONTEXT) {std::cout << "Failed to create egl context %{public}x, error:" << eglGetError() << std::endl;}// 创建eglSurfaceeglSurface_ = eglCreateWindowSurface(eglDisplay_, config_, eglNativeWindow_, context_attribs);if (eglSurface_ == EGL_NO_SURFACE) {std::cout << "Failed to create egl surface %{public}x, error:" << eglGetError() << std::endl;}// 关联上下文eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_);// EGL环境初始化完成std::cout << "Create EGL context successfully, version" << major << "." << minor << std::endl;
}
  1. 创建OH_NativeImage实例
// 创建 OpenGL 纹理
GLuint textureId;
glGenTextures(1, &textureId);
// 创建 NativeImage 实例,关联 OpenGL 纹理
OH_NativeImage* image = OH_NativeImage_Create(textureId, GL_TEXTURE_EXTERNAL_OES);
  1. 获取对应的数据生产者端NativeWindow
// 获取生产者NativeWindow
OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(image);
  1. 设置NativeWindow的宽高
int code = SET_BUFFER_GEOMETRY;
int32_t width = 800;
int32_t height = 600;
int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, code, width, height);
  1. 将生产的内容写入NativeWindowBuffer

  2. 从NativeWindow中获取NativeWindowBuffer。

OHNativeWindowBuffer *buffer = nullptr;
int fenceFd;
// 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &buffer, &fenceFd);BufferHandle *handle = OH_NativeWindow_GetBufferHandleFromNative(buffer);
  1. 将生产的内容写入NativeWindowBuffer。
#include <sys/mman.h>// 使用系统mmap接口拿到bufferHandle的内存虚拟地址
void *mappedAddr = mmap(handle->virAddr, handle->size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd, 0);
if (mappedAddr == MAP_FAILED) {// mmap failed
}
static uint32_t value = 0x00;
value++;
uint32_t *pixel = static_cast<uint32_t *>(mappedAddr);
for (uint32_t x = 0; x < width; x++) {for (uint32_t y = 0; y < height; y++) {*pixel++ = value;}
}
// 内存使用完记得去掉内存映射
int result = munmap(mappedAddr, handle->size);
if (result == -1) {// munmap failed
}
  1. 将NativeWindowBuffer提交到NativeWindow。
// 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为NativeWindowBuffer全部有内容更改。
Region region{nullptr, 0};
// 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
  1. 用完需要销毁NativeWindow。
OH_NativeWindow_DestroyNativeWindow(nativeWindow);
  1. 更新内容到OpenGL纹理
// 更新内容到OpenGL纹理。
ret = OH_NativeImage_UpdateSurfaceImage(image);
if (ret != 0) {std::cout << "OH_NativeImage_UpdateSurfaceImage failed" << std::endl;
}
// 获取最近调用OH_NativeImage_UpdateSurfaceImage的纹理图像的时间戳和变化矩阵。
int64_t timeStamp = OH_NativeImage_GetTimestamp(image);
float matrix[16];
ret = OH_NativeImage_GetTransformMatrix(image, matrix);
if (ret != 0) {std::cout << "OH_NativeImage_GetTransformMatrix failed" << std::endl;
}// 对update绑定到对应textureId的纹理做对应的opengl后处理后,将纹理上屏
EGLBoolean eglRet = eglSwapBuffers(eglDisplay_, eglSurface_);
if (eglRet == EGL_FALSE) {std::cout << "eglSwapBuffers failed" << std::endl;
}
  1. 解绑OpenGL纹理,绑定到新的外部纹理上
// 将OH_NativeImage实例从当前OpenGL ES上下文分离
ret = OH_NativeImage_DetachContext(image);
if (ret != 0) {std::cout << "OH_NativeImage_DetachContext failed" << std::endl;
}
// 将OH_NativeImage实例附加到当前OpenGL ES上下文, 且该OpenGL ES纹理会绑定到 GL_TEXTURE_EXTERNAL_OES, 并通过OH_NativeImage进行更新
GLuint textureId2;
glGenTextures(1, &textureId2);
ret = OH_NativeImage_AttachContext(image, textureId2);
  1. OH_NativeImage实例使用完需要销毁掉
// 销毁OH_NativeImage实例
OH_NativeImage_Destroy(&image);

最后呢

很多开发朋友不知道需要学习那些鸿蒙技术?鸿蒙开发岗位需要掌握那些核心技术点?为此鸿蒙的开发学习必须要系统性的进行。

而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。

在这里插入图片描述

针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细鸿蒙(OpenHarmony )手册(共计1236页)与鸿蒙(OpenHarmony )开发入门视频,帮助大家在技术的道路上更进一步。

  • 《鸿蒙 (OpenHarmony)开发学习视频》
  • 《鸿蒙生态应用开发V2.0白皮书》
  • 《鸿蒙 (OpenHarmony)开发基础到实战手册》
  • OpenHarmony北向、南向开发环境搭建
  • 《鸿蒙开发基础》
  • 《鸿蒙开发进阶》
  • 《鸿蒙开发实战》

在这里插入图片描述

总结

鸿蒙—作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。

并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿
1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/416538.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux系统中USB模块鼠标驱动实现

各位开发者大家好,今天主要给大家分享一下,Linux系统中使用libusb的方法以及鼠标驱动实现。 第一:libusb概述 参考网址:* libusb GIT仓库:https://github.com/libusb/libusb.git * libusb 官网:https://libusb.info/ * libusb API接口:https://libusb.sourceforge.io/…

mysql 使用 general 开启SQL跟踪功能

查看当前状态 mysql> SHOW VARIABLES LIKE %general%; 启用 临时启用 SET GLOBAL general_logon; SET GLOBAL general_log_file/tmp/general.log; 永久启用 通过修改配置文件来启用,需要重启mysql服务 [mysqld] general_logON general_log_file/tmp/general.log 再次查看状态…

【Redis】Redis 持久化机制详解:RDB、AOF 和混合持久化的工作原理及优劣分析

目录 持久化RDB触发机制流程说明RDB ⽂件的处理RDB 的优缺点 AOF使⽤ AOF命令写⼊⽂件同步重写机制启动时数据恢复 混合持久化小结 持久化 回顾 MySQL 的事务的特性&#xff1a; 原子性一致性持久性&#xff08;持久化&#xff09;隔离性 持久化&#xff1a;把数据存储在硬盘上…

CAN总线之一篇文章讲清楚Motorala和inter格式

前言&#xff1a; 之前的工作中&#xff0c;其实对Motorala和inter格式并不是了解的十分透彻。最近由于工作需要&#xff0c;研究了一下这两种格式&#xff0c;发现里面的门道其实挺复杂的。 特此作了一些总结&#xff1a;和大家一起分享。 我查了不少文档&#xff0c;描述其…

MongoDB 向 PostgreSQL 宣战

上周 MongoDB 发布了一份亮眼的季度财报&#xff0c;盘后股价涨幅超过 18%。 值得一提的是&#xff0c;MongoDB 的 CEO Dev Ittycheria 特别提到 MongoDB 正在借助自己的数据库服务 Atlas 从 PostgreSQL 那里挖角。原话是举了一个博彩网站的例子&#xff1a; “Initially, th…

【C++ 第十八章】C++11 新增语法(4)

前情回顾&#xff1a; 【C11 新增语法&#xff08;1&#xff09;&#xff1a;1~6 点】 C11出现与历史、花括号统一初始化、initializer_list初始化列表、 auto、decltype、nullptr、STL的一些新变化 【C11 新增语法&#xff08;2&#xff09;&#xff1a;7~8 点】 右值引用和…

uniapp插槽用法

目录 什么是插槽? 基本概念 默认插槽 命名插槽 作用域插槽 场景一:子插槽向父组件传递一个字符串 场景二:子插槽向父组件传递对象 什么是插槽? 在 UniApp 中&#xff0c;插槽&#xff08;Slot&#xff09;是一种允许父组件向子组件特定位置插入HTML内容的方式。这种方式使得组…

快速便捷地解决 reCAPTCHA 的方法

reCAPTCHA 是一种流行的挑战-响应系统&#xff0c;旨在通过提供人类易于解决但机器难以解决的难题来保护网站免受机器人和自动化滥用。无论您是处理网络抓取项目中的 reCAPTCHA 的开发人员&#xff0c;还是在各种网站上浏览的用户&#xff0c;了解如何有效地处理 reCAPTCHA 都可…

每日OJ_牛客_五子棋(判断是否有赢)

目录 牛客_五子棋&#xff08;判断是否有赢&#xff09; 解析代码 牛客_五子棋&#xff08;判断是否有赢&#xff09; 五子棋__牛客网 题目&#xff1a; 用例输入&#xff1a; .................... .................... .................... .................... ....…

基础闯关4

环境配置 我们来配置LlamaIndex实验环境&#xff0c;首先创建Python环境并安装必要的库&#xff1a; conda create -n llamaindex python3.10 conda activate llamaindex conda install pytorch2.0.1 torchvision0.15.2 torchaudio2.0.2 pytorch-cuda11.7 -c pytorch -c nvid…

VBA数据库解决方案第十四讲:如何在数据库中动态删除和建立数据表

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

Pixelmator Pro for Mac 专业图像处理软件【媲美PS的修图软件】

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

MySQL 使用C语言链接

mysql的基础&#xff0c;我们之前已经学过&#xff0c;后面我们只关心使用 要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作&#xff1a; 保证mysql服务有…

python常用库学习-Matplotlib使用

文章目录 安装 Matplotlib导入库基本示例1. 绘制简单的线图2. 散点图3. 柱状图4. 直方图5. 子图 更多高级功能1. 自定义样式2. 文本和注释3. 保存图形 示例&#xff1a;使用 Matplotlib 绘制多个图表示例 1: 绘制多个线图示例 2: 绘制散点图和直方图 参考文献 Matplotlib 是 Py…

MySQL数据库安装(详细)—>Mariadb的安装(day21)

该网盘链接有效期为7天&#xff0c;有需要评论区扣我&#xff1a; 通过网盘分享的文件&#xff1a;mariadb-10.3.7-winx64.msi 链接: https://pan.baidu.com/s/1-r_w3NuP8amhIEedmTkWsQ?pwd2ua7 提取码: 2ua7 1 双击打开安装软件 本次安装的是mariaDB&#xff0c;双击打开mar…

移动UI:成就勋章页面该如何设计,用例子说明。

移动应用的UI成就勋章页面通常是一个展示用户在应用中取得成就和获得勋章的页面。这种页面通常用于激励用户参与应用的活动&#xff0c;增加用户的参与度和忠诚度。 UI设计成就勋章页面时&#xff0c;一般会包括以下元素和功能&#xff1a; 1. 勋章列表&#xff1a; 展示用户…

集成电路学习:什么是ARM先进精简指令集计算机

ARM&#xff1a;先进精简指令集计算机 ARM先进精简指令集计算机&#xff08;Advanced RISC Machine&#xff0c;简称ARM&#xff09;是一种基于精简指令集计算机&#xff08;RISC&#xff09;原则的计算机处理器架构&#xff0c;由英国的ARM公司开发。这种架构以其低功耗和高性…

git创建本地分支并track跟踪远程分支

git创建本地分支并track跟踪远程分支 查看本地分支与远程分支的映射关系&#xff1a; git branch -vv 查看远程都有什么分支&#xff1a; git branch -r 在本地自动新建一个xxx分支&#xff0c;且自动track跟踪远程的同名xxx分支&#xff1a; git checkout --track origin/xx…

《黑神话:悟空》背后的渲染技术解析

《黑神话&#xff1a;悟空》作为备受瞩目的国产单机游戏&#xff0c;承载了深厚的文化底蕴&#xff0c;其背后的渲染技术无疑是推动其视觉表现达到新高度的关键。这款游戏不仅融合了传统与创新的角色设计&#xff0c;还通过一系列前沿的图形渲染技术&#xff0c;为玩家带来了前…

写的一致性问题之双写模式

文章目录 1、先写mysql&#xff1a;mysql会回滚&#xff0c;而redis不会回滚2、先写redis&#xff1a; 1、先写mysql&#xff1a;mysql会回滚&#xff0c;而redis不会回滚 写入msql成功&#xff0c;写入redis也成功&#xff0c;但是后续事务提交失败&#xff0c;mysql会回滚&a…