最近遇到一个需求,要求将一个GL_TEXTURE_2D类型的纹理ID写入到ImageReader生成的Surface中。

其实这个需求与我之前写过的一篇文章 一文学会MediaCodeC与OpenGL录制mp4视频需求比较接近,只需要对该案例源码进行一些改造即可。

在正式介绍实现之前,需先明确:

  • 什么是 android.view.Surface
  • 如何向Surface中写入数据?

一、Surface

什么是android.view.Surface

  • 用高大上方式(让人听不懂的方式)表述如下:

    android.view.Surface 是 Android 系统中一个重要的图形渲染类,它用于与硬件显示层进行通信,将图形数据渲染到屏幕上,可以用于实现多种功能,如视频播放、相机预览、屏幕录制等。

    Surface 对象代表了一个画布,可以在其上绘制图形,这些图形将通过硬件显示层呈现在屏幕上。可以在 SurfaceViewTextureViewWindowManager 等控件中使用 Surface 进行图形渲染。此外,Surface 还可以用于视频播放、相机预览、屏幕录制等功能。
  • 查阅官方描述、源码实现,总结为一句通俗易懂的话:

    Surface是一个Java层类,其持有一个Native (C层) 管理的图像缓冲区句柄。由图像缓冲区的消费者创建(如MediaRecorder),通过Surface将句柄传递给图像的生产者 (如MediaPlayer) 进行渲染。

1.1 官方描述

关于android.view.Surface官方描述如下:

翻译过来就是:

Surface 持有一个由屏幕合成器管理(Native层管理)的原始缓冲区的句柄。通常是由图像缓冲区的消费者(如 SurfaceTexture、MediaRecorder、Allocation等)创建或生成,并被传递给生产者(如 OpenGL、MediaPlayer、CameraDevice等)进行绘制。

因为,Surface 只是持有Native层缓冲区的句柄,若Native层的指针被释放后,则该Surface不再有效。

1.2 官方源码

查看Surface 源码,可以看到Surface 通过持有Native层的句柄mNativeObject来管理原始数据缓冲区。

1.3 官方文档

查看Surface 官方文档,查看其所有的公有方法:

看到上述公有方法后,发现除了通过lockCanvas()方法可以获取一个Canvas对象,然后使用drawBitmap()等API写入图形数据外,并无其他有用的方法,帮助我们实现TextureID纹理ID的写入。

二、向Surface写入数据

要向 Surface 持有的 mNativeObject 句柄中写入图像数据,我现在已知有两种方式:

  • 第一种方式是上文提到的通过Canvas写入;
  • 第二种方式是通过OpenGL写入,也就是本文的要介绍的重点;

2.1 通过Canvas写入

上文介绍到,在查看Surface的公有方法后,发现通过lockCanvas()方法可以获取一个Canvas对象,然后使用drawBitmap()等API写入图形数据,操作步骤如下:

  • 通过 SurfaceHolder 获取 Surface 对象;
  • 通过 Surface 对象的 lockCanvas() 方法获取 Canvas 对象;
  • 在 Canvas 上进行绘制操作,例如调用 drawBitmap() 方法绘制位图;
  • 通过 Canvas 对象的 unlockCanvasAndPost() 方法将绘制结果提交到 Surface 中,从而实现在屏幕上渲染数据。

以下为简单的代码举例:

SurfaceHolder holder = surfaceView.getHolder();
Surface surface = holder.getSurface();
Canvas canvas = surface.lockCanvas(null);
// 在 canvas 上进行绘制操作
canvas.drawBitmap(bitmap, 0, 0, null);
surface.unlockCanvasAndPost(canvas);

2.2 通过OpenGL写入

通过OpenGL向Surface中写入数据,其根本原理是:

将Surface绑定到一个EGLSurface上,然后通过OpenGL向EGLSurface渲染数据,最终将结果渲染到关联的Surface上。具体实现是使用 EGL 提供的 eglCreateWindowSurface() 函数,将 EGLSurfaceSurface 对象关联起来。然后就可以通过 OpenGL ES 将渲染结果绘制到 EGLSurface 中,最终渲染到Surface上。

其代码实现举例如下所示:

// 获取 EGLDisplay 对象
EGLDisplay mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
// 初始化 EGL 环境
int[] version = new int[2];
EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)
// 配置 attribList
int[] attribList = {
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_ALPHA_SIZE, 8,
//
EGL14.EGL_RENDERABLE_TYPE,
EGL14.EGL_OPENGL_ES2_BIT,
0x3142,
1,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
EGL14.eglChooseConfig(mEglDisplay, attribList, 0, configs, 0, configs.length, numConfigs, 0);
// 获取 EGLContext 上下文
EGLContext shareEglContext = inEglContext;
// 配置 EGLContext 属性
final int[] attrib_list = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
// 获取 EGLDisplay 对象
EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
// 创建一个 EGLSurface 对象(绑定surface)
EGLSurface eglSurface = EGL14.eglCreateWindowSurface(eglDisplay, configs[0], surface, surfaceAttribs, 0);
// 将 EGLSurface 和 EGLContext 绑定到 EGLDisplay 上
EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // 渲染图形 ... // 交换前后缓冲(将egl渲染结果交换到surface上)
EGL14.eglSwapBuffers(eglDisplay, eglSurface);

三、源码下载

将一个GL_TEXTURE_2D类型的纹理ID写入到ImageReader生成的Surface中,源码案例工程下载地址如下:

https://download.csdn.net/download/aiwusheng/87959680

案例代码实现流程流程如下:

  • OpenGLES3 中加载GL_TEXTURE_2D纹理,生成纹理ID;
  • 通过 EGL 构建 EGLDisplay 并绑定ImageReader提供的Surface
  • 在 EGL 线程中渲染GL_TEXTURE_2D对应的纹理图形;
  • 在 EGL 线程中完成渲染后,通过eglSwapBuffers交换缓冲数据;
  • 在 ImageReader 中 onImageAvailable 中读取Surface数据,并将数据保存为一张Bitmap;
  • 将的Bitmap显示到 ImageView 上(用于验证纹理ID是否正常写入到Surface)

案例源码效果图如下图所示:

= THE END =

一文学会TextureID渲染到Surface的更多相关文章

  1. 一文学会JVM性能优化

    实战性能优化 1 重新认知JVM 之前我们画过一张图,是从Class文件到类装载器,再到运行时数据区的过程,现在咱们把这张图不妨丰富完善一下,展示了JVM的大体物理结构图. 执行引擎:用于执行JVM字 ...

  2. 一文学会 TypeScript 的 82% 常用知识点(下)

    一文学会 TypeScript 的 82% 常用知识点(下) 前端专栏 2019-11-23 18:39:08     都已经 9021 年了,TypeScript(以下简称 TS)作为前端工程师不得 ...

  3. 一文学会text-justify,orientation,combine文本属性

    大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...

  4. 一文学会MySQL的explain工具

    开篇说明 (1) 本文将细致介绍MySQL的explain工具,是下一篇<一文读懂MySQL的索引机制及查询优化>的准备篇. (2) 本文主要基于MySQL5.7版本(https://de ...

  5. 【Flutter 实战】一文学会20多个动画组件

    老孟导读:此篇文章是 Flutter 动画系列文章第三篇,后续还有动画序列.过度动画.转场动画.自定义动画等. Flutter 系统提供了20多个动画组件,只要你把前面[动画核心](文末有链接)的文章 ...

  6. 一文学会Java的交互式编程环境jshell

    什么是交互式编程环境?重点词交互,在这样的编程环境中,你每输入一行代码,环境都会给你一个反馈,这就是交互式的编程环境.这种编程环境并不太适合工程化的复杂性需求,但在一些快速验证.简单计算之类的场景下还 ...

  7. 一文学会Scala

    整体介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. 联邦理工学院洛桑(EPFL)的Martin Odersky于2001 ...

  8. 一文学会matplotlib

    matplotlib基础 “““ 假设一天中每隔两个小时(range(2,26,2))的气温(℃)分别是[15,13,14.5,17,20,25,26,26,27,22,18,15] 用matplot ...

  9. 渲染路径-surface shader 光照函数与渲染路径

    https://docs.unity3d.com/Manual/SL-SurfaceShaderLighting.html Lighting Model declaration Lighting mo ...

  10. 一文学会Java死锁和CPU 100% 问题的排查技巧

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开 工欲善其事,必先利其器 00 本文简介 作为一名搞技术的程序猿或者是攻城狮,想必你应该是对下面这两个问题有所了解,说不定你在 ...

随机推荐

  1. Yum安装svn及配置

    svn配置 1.安装svn服务器端 yum install subversion 从镜像下载安装svn服务器端 cd /usr/local/ //进入目录,准备创建svn目录 mkdir svn // ...

  2. 一文吃透Elasticsearch

    本文已经收录到Github仓库,该仓库包含计算机基础.Java基础.多线程.JVM.数据库.Redis.Spring.Mybatis.SpringMVC.SpringBoot.分布式.微服务.设计模式 ...

  3. 18-html压缩

    const { resolve } = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); modul ...

  4. Gradio入门到进阶全网最详细教程[二]:快速搭建AI算法可视化部署演示(侧重参数详解和案例实践)

    Gradio入门到进阶全网最详细教程[二]:快速搭建AI算法可视化部署演示(侧重参数详解和案例实践) 相关文章:Gradio入门到进阶全网最详细教程[一]:快速搭建AI算法可视化部署演示(侧重项目搭建 ...

  5. 深度相机(TOF)的工作原理

    文章目录 深度相机(TOF)的工作原理 TOF由什么组成? 一.TOF相机采用主动光探测,通常包括以下几个部分: 二.TOF是如何测距的呢? 三.TOF会受什么影响? 四.那TOF相机最后输出的是什么 ...

  6. Python 创建数字列表

    创建数字列表 用于存储数字集合,高效地处理数字列表 使用函数range() range(value1,value2),从指定的第一个值开始数,到达指定的第二个值后停止,输出不包含第二个值 使用rang ...

  7. #Powerbi 利用动态格式字符串功能,实现百分数智能缩位(powerbi4月重磅更新功能)

    以下内容(基于POWERBI 23年4月更新的最新版本) 实际业务中,日常报表一般都有一个较为规范的百分数缩位要求,如果统一要求保留一位小数,那么在有些时候,我们会面临被缩成0.0%的尴尬,例如原有的 ...

  8. 大米cms爆破后台及支付逻辑漏洞

    又找到个网站挖洞,我来康康. 大米手机是个什么鬼手机??看一下吧 这个支付页面好熟悉,可能存在支付逻辑漏洞,咱们用burp改个包看看. 先支付一个看看 把包里那个=1改成0试试~ 证实确实存在支付逻辑 ...

  9. Alist云盘视频加密助手:支持云盘视频文件加密与在线播放,不用再担心视频文件被和谐了!

    在当前娱乐资源丰富的时代,人们每天都在接触各种视频资源.然而,网盘限速.版权审核.视频分级.少儿不宜等问题经常让人感到困扰.如何在保护隐私的前提下,让视频存储和分享变得更加便捷.安全呢?分享一款实用的 ...

  10. DataGridViewImageColumn 图片照片

    Private Sub BT_PHOTOADDRESS_Click(sender As Object, e As EventArgs) Handles BT_PHOTOADDRESS.Click Di ...