上文我们说到如何使用GLSurfaceView 进行camera预览,但是关于camera的预览数据是如何渲染到屏幕上的还是一头雾水,下面我们就结合源码,说一说GLSurfaceView 渲染的那些事。
一、还是从camera预览作为切入点,在预览的时候会创建和绑定一个纹理即SurfaceTexture,然后通过Camera调用setPreviewTexture并将创建的纹理做为参数传进去。然后Camera会同JNI桥梁调用到Camera.cpp中
获取IGraphicBufferProducer本地代理gbp,然后传给Service端camera->setPreviewTarget(gbp)。当打开一个Camera时会实例一个Client,然后由Client去设置一个预览的窗口。
当ap端设置完Camera参数开启预览startPreview,通过IPC通知Client状态改为previewEnabled,然后Client端会调用Camera的硬件接口层初始化预览窗口信息。
camera预览就介绍这里,本文的重点是介绍数据的渲染。
二、回过头在来看下MyGLSurface代码。
深入源码看下setRenderer都干了什么。
setRenderer函数主要干了2件事,一个是给View设置一个渲染器对象二是开启渲染线程。线程start后执行guardedRun,run函数一个while(true)循环,渲染数据。
到此我们看见了一个关键词Draw,draw大家都很熟悉,给个Paint和Canvas就可以往画布上画东西了。但是画布我们已经有了就是当前这个View,但是画什么呢?
前面我们说预览的时候会给Camera创建一个纹理,这个纹理会和我们渲染关系吗?在继续往下面看代码
从上述代码中看跟SurfaceTexture有关的就2个函数updateTexImage和getTransformMatrix,我们一个一个分析,先看updateTexImage函数,
updateTexImage函数注释是这样写的:Update the texture image to the most recent frame from the image stream,意思是说,从OpenGL上下文线程,即当前渲染线程中更新图像数据流最近的一帧纹理图像。也是通过JNI桥梁获取到GLConsumer然后调用GLConsumer对象的updateTexImage,如图:
上述流程总结下大致是这样的。
1、获取BufferItem,创建EglImage对象
2、更新GLConsumer状态,computeCurrentTransformMatrixLocked对当前的buffer进行矩阵变换处理
3、绑定EglImage到GL texture,doGLFenceWaitLocked,判断当前mCurrentFence是否有效。等待新的buffer ready。
二、getTransformMatrix
获取刚刚计算得到的变换矩阵。然后调用OpenGL接口开始绘制。
以上就是对渲染这部分的解析,可能会有些不太准备的地方,还请各位指正。
下面是上述分析中涉及到源码部分的路径:
原创不易,如果您觉得好,可以分享此公众号给你更多的人。