参考了:
https://www.jianshu.com/p/369d5694c8ca
使用Renderer,在GLSurfaceView里画。
class MyGLSurfaceView extends GLSurfaceView {
public MyGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setRenderer(new MyRender());
}
private static class MyRender implements Renderer {
...
@override void onDrawFrame(GL10 gl) {
调用gl的方法去画
}
}
}
GLSurfaceView中,局部变量gl的创建
** 更关心的是renderer是画到哪个Surface上? - 是在创建mEglHelper.mEGLSurface时,把SurfaceView.mSurfaceHolder传了过去,而SurfaceView.mSurfaceHolde是WMS获取的。 **
创建GLSurfaceView.mEglHelper.mEelSurface时,除了传SurfaceView.mSurfaceHolder,还传了GLSurfaceView.mEglHelper.mEglDisplay和GLSurfaceView.mEglHelper.mEglConfig
class GLSurfaceView {
class GLThread extends Thread {
run () {
guardedRun();
}
void guardedRun() {
try {
while(true) {
synchronized (sGLThreadManager) {
while (true) {
if (mShouldExit) {
return; //线程结束
}
if (readyToDraw()) {
if (!mHaveEglContext) {
if (askedToReleaseEglContext) {
} else {
try {
mEglHelper.start(); //做一些初始化,创建Egl和EglContext。Egl对应EGLImpl,EglContext对应的是EglContextImpl
}
mHaveEglContext = true;
}
}
if (mHaveEglContext && !mHaveEglSurface) { //有context,却没有surface时,准备创建surface
createEglSurface = true;
createGlInterface = true;
}
}
}
} //synchronized 结束
if (createEglSurface) {
if (mEglHelper.createSurface()) { //创建Surface,EGLWindowSurfaceFactory默认时,是通过EGLImpl创建的。创建时,会把SurfaceView.mSurfaceHolder传过去,就可以获取到suface
}
createEglSurface = false;
}
if (createGlInterface) { //此时,mEglHelper里的mEgl\ mEglSurface\ mEglContext都创建好了
gl = (GL10) mEglHelper.createGL(); //然后,让helper创建GL
}
if (createEglContext) {
if (view != null) {
view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); // Renderer的回调
}
createEglContext = false;
}
...
{
if (view !- null) {
view.mRenderer.onDrawFrame(gl); //可以在这个回调里画了
}
}
int swapError = mEglHelper.swap();
}// 外层while结束
}
}
}
}
GLSurfaceView {
static class EglHelper {
void start() {
mEgl = (EGL10) EGLContext.getEGL(); //获取EGL,egl是什么?-是Embeded graphy interface(不知道为啥最后一个是i)。 用途?- openGL 用于绘制,绘制完的书序要传给显示硬件来真正显示到屏幕上,egl就是把数据传给硬件的接口
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); //代表屏幕
if (!mEgl.eglInitialize(mEglDisplay, version)) { //egl有很多个版本,指定一个版本
}
if (view == null) {
} else {
// egl 与硬件打交道。显示看起来相同的图像,可以有很多配置方案,比如每个像素点用几个bit来表示。
// 使用mEgl.eglChooseConfig(...)接口,获取符合我们要求的 eglConfig。
// 这里又筛选了一次,找到想要的config
mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
}
}
boolean createSurface() {
...
if (view != null) {
// 有3种surface:windowSurface、 eglCreatePbufferSurface、 eglCreatePixmapSurface
// 有2种绘制模式:backBuffer \ singleBuffer
// 其中,windowSurface和 PbufferSurface使用的是back buffer; pixmapSurface使用 singleBuffer。
// 这里是创建的windowSurface。绘制时先画到backBuffer上,然后调用eglSwapBuffer()显示到屏幕上。surface理解为buffer更直接。
mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
mEglDisplay, mEglConfig, view.getHolder());
}
...
//把context绑定到drawSurface、readSurface、当前绘制线程。jni中,context会绑定到GLThread上,这样GLThread调用gl* 命令时,就可以画到surface上
// display作为 surface的前端显示。
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
}
}
int swap() {
// 不是display 与 surface交换
// 而是 surface有2个缓存时,surface自己的缓存切换,显示到对应的display屏幕上
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
}
}
}
}