GLSurfaceView、SS项目中滤镜模块、滤镜算法

一、准备工作

预览时就会开启的一些算法:

算法做在上层使用GLSurfaceView在预览时进行渲染:PHOTO、VIDEO、MACRO模式下的滤镜和美颜、FOOD模式下的冷暖色调、贴纸模式下的水印邮戳效果

算法做在底层使用SurfaceView预览:EIS视频防抖、虚化(人像、美食)、夜景模式、贴纸模式下的鬼脸效果

为什么需要使用GLSurfaceView(和SurfaceView的区别):

GLSurfaceView是继承自SurfaceView的,我们可以在源码中找到它的打包路径:

package android.opengl;

从这里我们可以知道,GLSurfaceView是Google为了方便Android开发者在设备上使用openGL ES进行相应渲染添加的一个View,SurfaceView我们知道,他也是一个Window上的View,按理来说应该和窗口中其他View共享一个Surface,但是他拥有一个自己的Surface,对这个Surface的渲染可以单独放在一个线程里面去,不会影响主线程事件的相应,GLSurafeceView与SurfaceView相比,加入了对EGL的管理(例如对EGLDisplay、自定义渲染器render的管理),这里我们首先要知道EGL是什么?

首先我们看Android官方对EGL的解释:

OpenGL ES 定义了一个渲染图形的 API,但没有定义窗口系统。为了让 GLES 能够适合各种平台,GLES 将与知道如何通过操作系统创建和访问窗口的库结合使用。用于 Android 的库称为 EGL。

通俗的将就是:OpenGL ES是一个全平台通用的绘制渲染API,我们需要在Android平台上使用,则需要一个中间层做适配,这个中间层就叫EGL。

在这里插入图片描述

这是EGL框架的架构,将真实设备的显示界面抽象为一个EGLDisplay,将存储图像信息的FrameBuffer抽象成为一个EGLSurface,将与OpenGL ES交互的绘图时的一些状态信息抽象成一个EGLContext。如果我们不使用GLSurfaceView在屏幕上渲染绘制图形的话,纯使用EGL框架进行绘图,按照一般步骤来看,大概需要前后11个操作:

  1. 获取EGLDisplay对象
  2. 初始化与EGLDisplay 之间的连接。
  3. 获取EGLConfig对象
  4. 创建EGLContext 实例
  5. 创建EGLSurface实例
  6. 连接EGLContext和EGLSurface.
  7. 使用GL指令绘制图形
  8. 断开并释放与EGLSurface关联的EGLContext对象
  9. 删除EGLSurface对象
  10. 删除EGLContext对象
  11. 终止与EGLDisplay之间的连接。

知道了EGL是什么之后,我们就要知道GLSurfaceView他是怎么样加入了对EGL的管理的?这就不得不谈到GLSurfaceView的整个渲染过程了。

在这里插入图片描述

首先看GLSurfaceView的类图,可以看到里面有两个最重要的静态内部类GLThread和EglHelper和一个供外层实现的接口Renderer。

1.GLSurfaceView.Renderer

我们先看这个接口,onSurfaceCreated()onSurfaceChanged()的回调是在GLSurfaceView成功创建和发生改变的时候调用,重要是这个onDrawFrame()方法的回调,这个方法的触发和给GLThread设置的渲染刷新模式有关,如果设置的是RENDERMODE_CONTINUOUSLY循环刷新模式,则会在子线程的一个while方法体中不断自动触发,如果设置的是RENDERMODE_WHEN_DIRTY,则需要手动调用一次requestRender()相对应的就能触发一次onDrawFrame()进行OpenGL的渲染,总结一下就是我们可以自定义我们所需要的渲染器,让其实现GLSurfaceView.Renderer接口,通过其中的三个回调方法,与相应的GLSurfaceView的创建和改变的生命周期回调绑定起来,同时在onDrawFrame的回调中处理相应的渲染逻辑,使用OpenGL ES进行渲染。

2.GLThread

GLThread就是我们一直所说的GL线程,是与OpenGL ES环境进行交互的线程,他会在setRederer的时候启动,内部采用的是while循环,通过标志位控制和线程的wait()notifyAll()方法,不停地等待和处理事件,所有的渲染工作都是做在这个线程里面的。

3.EglHelper

EglHelper顾名思义,可以看出这是一个帮助类,这是GLSurfaceView中帮我们封装好的,它能完成EGL绘图的绝大部分操作,例如在线程中已经做好了绘制的准备工作后,调用EglHelper的start()方法,在这里面会帮我们创建Egl实例,获得EGLDisplay的对象,随后会去创建与OpenGL ES交互的上下文EGLContext、渲染呈现的EGLSurface,最后创建GL对象,也就是获得OpenGL ES的编程接口。

在这里插入图片描述

从这张图我们可以看出GLSurfaceView渲染的主要流程,首先为GLSurfaceView设置自定义的渲染器,并且只能为其设置一次,所以会进行版本和渲染器状态的检查,如果是第二次设置渲染器,则会抛出异常,随后使用GLSurfaceView的一个弱引用去开启GLThread渲染进程

private final WeakReference<GLSurfaceView> mThisWeakRef = new WeakReference<GLSurfaceView>(this);

最重要的东西都在GLThread中的guardedRun()中完成,在这里完成类整个EGL绘制的所有步骤,mEglHelper的start()方法中,使用本地代码的JNI调用接口实例化一个EGL对象

private static final EGL EGL_INSTANCE = new com.google.android.gles_jni.EGLImpl();

再通过本地的Native方法获取EGLDisplay对象,初始化与EGLDisplay之间的连接,获取EGLConfig对象并创建了EGLContext 实例
在这里插入图片描述

在这里插入图片描述

接下来走到mEglHelper的createSurface()方法中,主要完成两个操作,创建EGLSurface并且将其与前面生成的EGLContext进行绑定

在这里插入图片描述
在这里插入图片描述

最后就回调到我们自己定义的GLSurfaveView.Renderer渲染器的三部曲方法里面,并且可以使用GL指令去绘制和渲染图形了

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

源码里为每一次回调的流程都加了trace,可以方便我们分析性能问题。到这里,你以为整个GLSsurface的绘制流程就结束了吗,其实并没有,我们回调到自定义渲染器的onDrawFrame方法里时,他确实是根据我们自定义的渲染模式开始渲染了,但我们并没有将它渲染完的东西填充到我们的显示Surface上去,准确地说,是EGLSurface上的数据和我们用来显示的Surface并没有交互,也可以这么说,EGLSurface里面的一个渲染好的FrameBuffer(你可以叫他内存缓冲区,也可以叫他渲染目的地),并有呈现在我们自己的mSurface上,所以缺少了最关键的一步,通过mEglHelper.swap()方法调用本地eglSwapBuffers()方法,交换缓冲区。

在这里插入图片描述

这里我特意追到安卓源码里看了一下他的实现,发现有两套实现交换缓冲区的方法,一种是原生的,另外一种是经过Android优化的eglSwapBuffersWithDamageKHR()方法,关于他的具体实现有几百行,关系到如何使用同步栅fence(安卓渲染里面的一种同步手段 我也不懂)来通知GPU和CPU的渲染和显示顺序之类的,然后openGL实现的代码又没有开源,所以就没有继续看下去了,但是我们可以知道它的原理。因为绝大多数情况下我们的Surface都是有一个双缓冲机制的,它包括前端显示的缓冲区front-buffer和后端存储渲染结果的缓冲区back-surface,只有前端缓冲区的东西可以用于EGLDisplay,所以我们必须把后端渲染完成后的缓冲区内容和前端进行交换,才可以将渲染后的图形信息填充到Surface上,进一步显示到我们的设备上。

至此,整个GLSurfaceView一帧的渲染过程就结束了,回到我们的主题,GLSurfaceView又是怎么样方便地对EGL进行管理的呢?其实我相信大家都已经看出来了,那就是我们使用GLSurfaceView进行渲染的话,我们只需要关心我们自己的渲染器Renderer如何实现,其他的完全不用关心,因为GLSurfaceView内部都已经帮我们封装好了,我们只需要在Renderer接口的三个回调中处理我们相应的事件和逻辑,并将我们自己的渲染器给GLSurfaveView设置好就行。

持续更新 待补充。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值