EGL全称:Embedded-System Graphics Library。
显示设备的参数设置有十多种,不同硬件系统之间差异很大,比如有的不支持RGB_565,所以维护OpenGLES的khronos组织专门抽出一层,以适配各平台的差异,这个抽象层即EGL。
OpenGLES定义了平台无关的GL绘图指令,EGL则定义了控制 displays、contexts 以及 surfaces 的统一的平台接口。
java是跨平台的,是因为java虚拟机打平了各平台的差异。同理,EGL打平了各平台底层图形硬件的差异,所以openGL ES才能跨平台。类似的功能库有SDL、GLFW、GLUT等。
下文中GL指的OpenGL ES,不再说明。
为什么要用到EGL
基于GLSurfaceView,就可以很简单的继成GL,Android平台替开发者屏蔽了复杂的EGL,懂一点GL就可以渲染酷炫的效果,在图像、视频处理中有广泛的应用。
弊端是,如果有比较复杂的定制,GLSurfaceView就不够用了。比如应用中有多个GL环境,需要动态切换,或多个GL环境需要共享GLContext(context保存了GL的状态、资源),而GLSurfaceView中EGL的实现是默认写死的。
GLSurfaceView源码中,有一个EglHelper类处理了EGL初始化配置的逻辑,后面还会讲到。
Java层配置EGL,自定义GLSurfaceView,参考
继成SurfaceView,完整实现一个GLSurfaceView,就很清楚的了解GLSurfaceView替我们干了啥。
把最核心的逻辑抠出来,画了张流程图:
GLSurfaceView的工作流程:
设置Renderer
addCallback(SurfaceView方法)
实现EGLThread(常说的渲染线程)
初始化EGL
while(true)中循环调用onSurfaceCreated()、onSurfaceChanged()、onDrawFrame()
从实现EglHelper.java开始,仿照GLSurfaceView自己实现一遍
实现EglHelper,封装EGL初始化逻辑
EGL像个中介,把Display、Surface、Context绑到一起,让这三者结合到一起,紧密配合,碰撞出爱的火花。初始化及绑定的工作封装在EglHelper中。
上图用代码实现,流程如下:
EGL实例
得到Egl实例
Display
得到默认的显示设备(就是窗口)
初始化默认显示设备
设置显示设备的属性
从系统中获取对应属性的配置
Context
创建EglContext
Surface
创建渲染的Surface
绑定EglContext和Surface到显示设备中
渲染到屏幕
刷新数据,显示渲染场景
EGL设置略繁琐,但是逻辑并不复杂,详细参考github代码
GLSurfaceView实现
GLSurfaceView最核心的逻辑是实现了GLThread,该线程中处理了EGL初始化,以及drawFrame等重要回调
GLThread run()函数实现比较重要单独拿出来看看,完整代码参考
重点关注:
EGLHelper初始化
不同的RenderMode,如何处理
onCreate() onChange(width, height) onDraw()回调时机
@Override
public void run() {
super.run();
try {
guardedRun();
} catch (InterruptedException e) {
e.printStackTrace();
private void guardedRun() throws InterruptedException {
isExit = false;
isStart = false;
object = new Object();
mEglHelper = new EglHelper();
mEglHelper.initEgl(mEGLSurfaceViewWeakRef.get().mSurface, mEGLSurfaceViewWeakRef.get().mEglContext);
while (true) {
if (isExit) {
release();
break;
if (isStart) {
if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_WHEN_DIRTY) {
synchronized(object) {
object.wait();
} else if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_CONTINUOUSLY) {
Thread.sleep(1000 / 60);
} else {
throw new IllegalArgumentException("renderMode");
onCreate();
onChange(width, height);
onDraw();
isStart = true;
Activity中使用自定义的GLSurfaceView
demo很简单,点击GLSurfaceView,触发更改颜色。重要的是把整个流程串起来,弄明白了,可以使用OpenGL定义更有意思的效果。
实现效果:
完成Demo:
public class EglMainActivity extends AppCompatActivity implements EglSurfaceView.Renderer{
public static final String TAG = "EglMainActivity";
private EglSurfaceView eglSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
eglSurfaceView = new EglSurfaceView(this);
setContentView(eglSurfaceView);
eglSurfaceView.setRenderer(this);
eglSurfaceView.setRendererMode(EglSurfaceView.RENDERMODE_WHEN_DIRTY);
eglSurfaceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
eglSurfaceView.requestRender();
@Override
public void onSurfaceCreated() {
Log.e(TAG, "onSurfaceCreated");
@Override
public void onSurfaceChanged(int width, int height) {
Log.e(TAG, "onSurfaceChanged");
GLES20.glViewport(0, 0, width, height);
@Override
public void onDrawFrame() {
Log.e(TAG, "onDrawFrame");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
float r = (float) Math.random();
float g = (float) Math.random();
float b = (float) Math.random();
GLES20.glClearColor(r, g, b, 1.0f);
GL线程分析,这篇文章讲的非常好,建议认真阅读
EGL OpenGLES版本选择说明参考
Native层配置EGL
开发复杂的渲染功能时,opengl egl相关的代码放到C++层更方便,比如搭建一个渲染引擎,大多数库都是c++版本的。另一方面,C++层执行逻辑效率会高一些。
需要对NDK、C++开发有一定的了解。
接下来,我们讲讲Native方式配置EGL,逻辑和Java层的差不多。
完整工程:
github.com/summer-go/A…
重点讲不一样的地方:
Android Studio 新建C++工程
工程目录:
代码逻辑:
CMakeLists.txt配置
cmake_minimum_required(VERSION 3.4.1)
add_library(
native-lib
SHARED
native-lib.cpp
egl/EglHelper.cpp
egl/EglThread.cpp
find_library(
log-lib
log)
target_link_libraries(
native-lib
${log-lib}
GLESv2
android
实现EglHelper.cpp EglThread.cpp
逻辑与java层差不多,换成c++实现而已,详细参考工程代码
封装jni
jni逻辑放在native-lib.cpp,是C++工程自动创建的文件,名字我也懒得改,就在里面造了。比较简单:
EglThread *eglThread = NULL;
void callBackOnCreate(){
LOGE("callBackOnCreate");
void callBackOnChange(int width, int height){
LOGE("callBackOnChange");
void callBackOnDraw(){
glClearColor(0.0, 1.0, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
LOGE("callBackOnDraw");
extern "C"
JNIEXPORT void JNICALL
Java_com_android_samples_nativeegl_opengl_NativeOpenGL_nativeSurfaceCreate(JNIEnv *env,jobject thiz,jobject surface) {
eglThread = new EglThread();
eglThread->callBackOnCreate(callBackOnCreate);
eglThread->callBackOnChange(callBackOnChange);
eglThread->callBackOnDraw(callBackOnDraw);
eglThread->setRenderModule(RENDER_MODULE_MANUAL);
ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
eglThread->onSurfaceCreate(nativeWindow);
extern "C"
JNIEXPORT void JNICALL
Java_com_android_samples_nativeegl_opengl_NativeOpenGL_nativeSurfaceChanged(JNIEnv *env, jobject thiz,jint width,jint height) {
if(eglThread){
eglThread->onSurfaceChange(width, height);
extern "C"
JNIEXPORT void JNICALL
Java_com_android_samples_nativeegl_opengl_NativeOpenGL_nativeSurfaceDestroyed(JNIEnv *env,jobject thiz) {
if(eglThread){
eglThread->isExit = true;
pthread_join(eglThread->mEglThread, NULL);
delete eglThread;
eglThread = NULL;
NativeGLSurfaceView实现
NativeGLSurfaceView继承SurfaceView,几乎是个壳子,关键方法里调到Native方法
class NativeGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private NativeOpenGL mNativeOpenGL;
public NativeGLSurfaceView(Context context) {
this(context, null);
public NativeGLSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public NativeGLSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mNativeOpenGL = new NativeOpenGL();
getHolder().addCallback(this);
@Override
public void surfaceCreated(SurfaceHolder holder) {
mNativeOpenGL.nativeSurfaceCreate(holder.getSurface());
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mNativeOpenGL.nativeSurfaceChanged(width, height);
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mNativeOpenGL.nativeSurfaceDestroyed();
NativeOpenGL封装Native方法 java层接口
so easy
class NativeOpenGL {
static {
System.loadLibrary("native-lib");
public native void nativeSurfaceCreate(Surface surface);
public native void nativeSurfaceChanged(int width, int height);
public native void nativeSurfaceDestroyed();
最后在Activity中调用NativeGLSurfaceView
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SurfaceView写在布局中
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.android.samples.nativeegl.opengl.NativeGLSurfaceView
android:id="@+id/sample_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
实现效果很简单,随便画个颜色
你也可以改成自己喜欢的颜色
修改native-lib.cpp callBackOnDraw方法
void callBackOnDraw(){
glClearColor(0.0, 1.0, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
LOGE("callBackOnDraw");
开发一个完整的demo,涉及到不少细节,无法在一篇文章中详细阐述,读者朋友们有时间,可以读读文末附录的参考
欢迎关注公众号:sumsmile /专注图像处理的移动开发老兵~~
Android配置EGL环境: www.jianshu.com/p/ce3496ab9…
Android自定义GLSurfaceView: www.jianshu.com/p/08f9338ae…
EglHelper实现: github.com/summer-go/A…
EglSurfaceView实现: github.com/summer-go/A…
剖析EGL及GL线程源码: cloud.tencent.com/developer/a…
EGL OpenGLES版本选择: www.cnblogs.com/kiffa/archi…
eglmakeCurrent api: www.khronos.org/registry/EG…;
makeCurrent、eglSwapBuffers: www.zybuluo.com/SR1s/note/6…
非常棒的EGL opengl示意图: www.icode9.com/content-4-6…
c++ lock使用: blog.csdn.net/u012109245/…
android c++ EGL环境实现: www.jianshu.com/p/cb34f965a…