应用程序的渲染方式分为两种
- 按需渲染: 绝大多数应用程序,比如微信/钉钉/QQ,都是这种,当有数据更新才请求重新刷新绘制界面
- 定频渲染:比如游戏,永远按照固定的频率进行渲染(只有这样,才能模拟出逼真的动画效果)
在android 中,上述两个场景分别用以下两个类
- SurfaceView(按需渲染):直接在UI线程进行渲染,效率低,适用于渲染频率低的应用场景。
- GLSurfaceView(定频渲染):开启一个独立的opengl线程来进行渲染(防止UI线程被阻塞),每个GLSurfaceView的实例都有一个
GLThread mGLThread
成员
无论是java/C++, opengl绘制流程都一样:
- 初始化 egl 参数
- 在一个循环中不断进行帧绘制
类的大体定义如下
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2
{
private GLThread mGLThread; //独立的opengl线程进行渲染
private Renderer mRenderer; //自定义的Renderer, 这个Render定义了如何进行渲染
........
public void setRenderer(Renderer renderer)
{
.........
mRenderer = renderer;
mGLThread = new GLThread(mThisWeakRef);
mGLThread.start(); //启动opengl线程
}
public void queueEvent(Runnable r) {
mGLThread.queueEvent(r);
}
.........
}
public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
SurfaceControl mSurfaceControl; // 与android系统的的surfacefinger服务进行binder通讯
public void draw(Canvas canvas){
.....
super.draw(canvas);
}
}
static class GLThread extends Thread {
@Override
public void run() {
setName("GLThread " + getId());
if (LOG_THREADS) {
Log.i("GLThread", "starting tid=" + getId());
}
try {
guardedRun();
} catch (InterruptedException e) {
// fall thru and exit normally
} finally {
sGLThreadManager.threadExiting(this);
}
}
private void guardedRun() throws InterruptedException
{
.............
Runnable event = null;
while(true){
synchronized (sGLThreadManager) {
while (true) {
if (mShouldExit) {
return;
}
//pop 一个 event
if (! mEventQueue.isEmpty()) {
event = mEventQueue.remove(0);
break;
}
if (event != null) {
event.run(); // 执行event
event = null;
continue;
}
...........
// 初始化egl
mEglHelper.createGL();
...........
//onSurfaceCreated
mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
if(sizeChanged) //如果view大小发生了变化
{
//onSurfaceChanged
mRenderer.onSurfaceChanged(gl, w, h);
}
//绘制
mRenderer.onDrawFrame(gl);
...........
}
}
}
}
}
自定义Render类
public class MyRender implements GLSurfaceView.Renderer {
private int m_vbo;
private int m_textureId;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//初始化vbo,纹理 ,sharder 等
Log.d(TAG, "onSurfaceCreated");
GLES30.glClearColor(1.0f,0.0f,0.0f,1.0f);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d(TAG, "onSurfaceChanged");
GLES30.glViewport(0,0, width, height);
}
//调用 native 层的opengl库进行渲染
@Override
public void onDrawFrame(GL10 gl) {
GLES30.glClearColor(0.0f,0.0f,0.0f,1.0f);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, m_textureId);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, m_vbo);
..............
}
}
总结:GLSurfaceView 开启了独立的线程中进行opengl渲染,用Render类来定义具体如何渲染,在需要实时渲染的场景使用:比如 游戏,VR, 车载环视系统等。