1 前言
Android 中,GLSurfaceView 封装了 EGL 环境,使得我们省去了复杂的 EGL 环境搭建。如果我们不用 GLSurfaceView,该如何渲染 OpenGL ES 图像?在回答此问题前,我们先了解下 EGL。
EGL 是 Khronos Group 定义的平台无关接口,作为 OpenGL ES 和本地窗口系统之间的桥梁,主要功能如下。
- 管理图形上下文
- 创建和管理渲染表面 (surface)
- 同步渲染与平台显示系统
EGL 提供了两种渲染方式,分别是离屏渲染和窗口渲染,分别对应 eglCreatePbufferSurface 和 eglCreateWindowSurface。对于离屏渲染方案,详见 → EGL+FBO离屏渲染。eglCreateWindowSurface 函数的源码如下。- public static EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
- EGLConfig config, Object win, int[] attrib_list, int offset){
- Surface sur = null;
- if (win instanceof SurfaceView) {
- SurfaceView surfaceView = (SurfaceView)win;
- sur = surfaceView.getHolder().getSurface();
- } else if (win instanceof SurfaceHolder) {
- SurfaceHolder holder = (SurfaceHolder)win;
- sur = holder.getSurface();
- } else if (win instanceof Surface) {
- sur = (Surface) win;
- }
- EGLSurface surface;
- if (sur != null) {
- surface = _eglCreateWindowSurface(dpy, config, sur, attrib_list, offset);
- } else if (win instanceof SurfaceTexture) {
- surface = _eglCreateWindowSurfaceTexture(dpy, config,
- win, attrib_list, offset);
- } else {
- throw new java.lang.UnsupportedOperationException(
- "eglCreateWindowSurface() can only be called with an instance of " +
- "Surface, SurfaceView, SurfaceTexture or SurfaceHolder at the moment, " +
- "this will be fixed later.");
- }
- return surface;
- }
复制代码 主要留意 win 参数,可以看到它可以是 SurfaceView、SurfaceHolder、Surface,本质都是为了获取 Surface。因此我们提供了以下两种渲染图像的方案。
- 继承 SurfaceView 方案:自定义一个 View 继承 SurfaceView,并实现 SurfaceHolder.Callback 接口,在 surfaceCreated 方法中将 this 或 getHolder() 传给 eglCreateWindowSurface 函数。
- 继承 TextureView 方案:自定义一个 View 继承 TextureView,并实现 TextureView.SurfaceTextureListener 接口,在 onSurfaceTextureAvailable 方法中会提供 SurfaceTexture,我们可以创建一个 Surface,并将 SurfaceTexture 传给 Surface,然后将创建的 Surface 传给 eglCreateWindowSurface 函数。
本文完整代码详见 → 不用GLSurfaceView,如何渲染图像。
2 继承 SurfaceView 方案
自定义一个 View 继承 SurfaceView,并实现 SurfaceHolder.Callback 接口,在 surfaceCreated 方法中将 this 或 getHolder() 传给 eglCreateWindowSurface 函数。
由于 GLSurfaceView 继承 SurfaceView,所以该方案很容易想到,只需要将 GLSurfaceView 的核心代码扣出来就行。
MainActivity.java- package com.zhyan8.egldemo;
- import android.os.Bundle;
- import androidx.appcompat.app.AppCompatActivity;
- public class MainActivity extends AppCompatActivity {
- private EGLSurfaceView mEglSurfaceView;
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mEglSurfaceView = new EGLSurfaceView(this);
- setContentView(mEglSurfaceView);
- mEglSurfaceView.setRenderer(new MyRenderer(this));
- }
- @Override
- protected void onResume() {
- super.onResume();
- mEglSurfaceView.requestRender();
- //mEglSurfaceView.startRender();
- }
- @Override
- protected void onPause() {
- super.onPause();
- mEglSurfaceView.stopRender();
- }
- }
复制代码 EGLSurfaceView.java- package com.zhyan8.egldemo;
- import android.content.Context;
- import android.opengl.EGL14;
- import android.opengl.EGLConfig;
- import android.opengl.EGLContext;
- import android.opengl.EGLDisplay;
- import android.opengl.EGLExt;
- import android.opengl.EGLSurface;
- import android.util.Log;
- import android.view.Choreographer;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import androidx.annotation.NonNull;
- /**
- * @author little fat sheep
- * 承载EGL环境的View, 类比GLSurfaceView
- */
- public class EGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
- private static final String TAG = "EGLSurfaceView";
- protected EGLDisplay mEGLDisplay;
- protected EGLConfig mEGLConfig;
- protected EGLContext mEGLContext;
- protected EGLSurface mEGLSurface;
- protected Context mContext;
- protected Renderer mRenderer;
- protected boolean mFirstCreateSurface = true;
- private Choreographer mChoreographer = Choreographer.getInstance();
- public EGLSurfaceView(Context context) {
- super(context);
- mContext = context;
- getHolder().addCallback(this);
- }
- // 设置渲染器
- public void setRenderer(Renderer renderer) {
- mRenderer = renderer;
- }
- // 开始持续渲染
- public void startRender() {
- Log.i(TAG, "startRender");
- mChoreographer.removeFrameCallback(mFrameCallback);
- mChoreographer.postFrameCallback(mFrameCallback);
- }
- // 暂停持续渲染
- public void stopRender() {
- Log.i(TAG, "stopRender");
- mChoreographer.removeFrameCallback(mFrameCallback);
- }
- // 请求渲染一帧
- public void requestRender() {
- mFrameCallback.doFrame(System.nanoTime());
- }
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- createDisplay();
- createConfig();
- createContext();
- }
- @Override
- public void surfaceCreated(@NonNull SurfaceHolder holder) { // 每次activity resume都会调用一次
- Log.i(TAG, "surfaceCreated, surface=" + holder.getSurface());
- createSurface();
- makeCurrent();
- if (mFirstCreateSurface) {
- mRenderer.onSurfaceCreated();
- mFirstCreateSurface = false;
- }
- }
- @Override
- public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
- Log.i(TAG, "surfaceChanged, width=" + width + ", height=" + height);
- mRenderer.onSurfaceChanged(width, height);
- }
- @Override
- public void surfaceDestroyed(@NonNull SurfaceHolder holder) { // 每次activity pause都会调用一次
- Log.i(TAG, "surfaceDestroyed");
- if (mEGLDisplay != null && mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- // 与显示设备解绑
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- // 销毁 EGLSurface
- if (mEGLSurface != null && mEGLSurface != EGL14.EGL_NO_SURFACE) {
- EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
- checkoutConfig("eglDestroySurface");
- mEGLSurface = null;
- }
- }
- }
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Log.i(TAG, "onDetachedFromWindow");
- stopRender();
- getHolder().removeCallback(this);
- if (mEGLDisplay != null && mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- // 与显示设备解绑
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- // 销毁 EGLSurface
- if (mEGLSurface != null && mEGLSurface != EGL14.EGL_NO_SURFACE) {
- EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
- checkoutConfig("eglDestroySurface");
- mEGLSurface = null;
- }
- // 销毁 EGLContext
- if (mEGLContext != null && mEGLContext != EGL14.EGL_NO_CONTEXT) {
- EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
- checkoutConfig("eglDestroyContext");
- mEGLContext = null;
- }
- // 销毁 EGLDisplay (显示设备)
- EGL14.eglTerminate(mEGLDisplay);
- checkoutConfig("eglTerminate");
- mEGLDisplay = null;
- }
- }
- // 1.创建EGLDisplay
- private void createDisplay() {
- mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- int[] versions = new int[2];
- EGL14.eglInitialize(mEGLDisplay, versions,0, versions, 1);
- checkoutConfig("eglInitialize");
- }
- // 2.创建EGLConfig
- private void createConfig() {
- if (mEGLDisplay != null && mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- EGLConfig[] configs = new EGLConfig[1];
- int[] configNum = new int[1];
- EGL14.eglChooseConfig(mEGLDisplay, mEGLConfigAttrs, 0, configs, 0,1, configNum, 0);
- if (configNum[0] > 0) {
- mEGLConfig = configs[0];
- }
- checkoutConfig("eglChooseConfig");
- }
- }
- // 3.创建EGLContext
- private void createContext() {
- if (mEGLConfig != null) {
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, mEGLConfig, EGL14.EGL_NO_CONTEXT, mEGLContextAttrs, 0);
- checkoutConfig("eglCreateContext");
- }
- }
- // 4.创建EGLSurface
- private void createSurface() {
- if (mEGLContext != null && mEGLContext != EGL14.EGL_NO_CONTEXT) {
- int[] eglSurfaceAttrs = { EGL14.EGL_NONE };
- //mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, getHolder(), eglSurfaceAttrs, 0);
- mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, this, eglSurfaceAttrs, 0);
- checkoutConfig("eglCreateWindowSurface");
- }
- }
- // 5.绑定EGLSurface和EGLContext到显示设备(EGLDisplay)
- private void makeCurrent() {
- if (mEGLSurface != null && mEGLSurface != EGL14.EGL_NO_SURFACE) {
- EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
- checkoutConfig("eglMakeCurrent");
- }
- }
- private void checkoutConfig(String tag) {
- int error = EGL14.eglGetError();
- if (error != EGL14.EGL_SUCCESS) {
- Log.e(TAG, tag + " error=0x" + Integer.toHexString(error));
- }
- }
- // EGLConfig参数
- private int[] mEGLConfigAttrs = {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_ALPHA_SIZE, 8,
- EGL14.EGL_DEPTH_SIZE, 8,
- //EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
- EGL14.EGL_RENDERABLE_TYPE, EGLExt.EGL_OPENGL_ES3_BIT_KHR,
- EGL14.EGL_NONE
- };
- // EGLContext参数
- private int[] mEGLContextAttrs = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 3,
- EGL14.EGL_NONE
- };
- Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
- @Override
- public void doFrame(long frameTimeNanos) {
- mChoreographer.postFrameCallback(mFrameCallback);
- if (mEGLSurface != null) {
- mRenderer.onDrawFrame();
- EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
- checkoutConfig("eglSwapBuffers");
- }
- }
- };
- /**
- * @author little fat sheep
- * 渲染器接口, 类比GLSurfaceView.Renderer
- */
- interface Renderer {
- void onSurfaceCreated();
- void onSurfaceChanged(int width, int height);
- void onDrawFrame();
- }
- }
复制代码 MyRenderer.java- package com.zhyan8.egldemo;
- import android.content.Context;
- import android.opengl.GLES30;
- import java.nio.FloatBuffer;
- public class MyRenderer implements EGLSurfaceView.Renderer {
- private FloatBuffer vertexBuffer;
- private FloatBuffer textureBuffer;
- private MyGLUtils mGLUtils;
- private int mTextureId;
- public MyRenderer(Context context) {
- mGLUtils = new MyGLUtils(context);
- getFloatBuffer();
- }
- @Override
- public void onSurfaceCreated() {
- //设置背景颜色
- GLES30.glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
- //编译着色器
- final int vertexShaderId = mGLUtils.compileShader(GLES30.GL_VERTEX_SHADER, R.raw.vertex_shader);
- final int fragmentShaderId = mGLUtils.compileShader(GLES30.GL_FRAGMENT_SHADER, R.raw.fragment_shader);
- //链接程序片段
- int programId = mGLUtils.linkProgram(vertexShaderId, fragmentShaderId);
- GLES30.glUseProgram(programId);
- mTextureId = mGLUtils.loadTexture(R.raw.girl);
- }
- @Override
- public void onSurfaceChanged(int width, int height) {
- //设置视图窗口
- GLES30.glViewport(0, 0, width, height);
- }
- @Override
- public void onDrawFrame() {
- //将颜色缓冲区设置为预设的颜色
- GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
- //启用顶点的数组句柄
- GLES30.glEnableVertexAttribArray(0);
- GLES30.glEnableVertexAttribArray(1);
- //准备顶点坐标和纹理坐标
- GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
- GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 0, textureBuffer);
- //激活纹理
- GLES30.glActiveTexture(GLES30.GL_TEXTURE);
- //绑定纹理
- GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId);
- //绘制贴图
- GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 4);
- //禁止顶点数组句柄
- GLES30.glDisableVertexAttribArray(0);
- GLES30.glDisableVertexAttribArray(1);
- }
- private void getFloatBuffer() {
- float[] vertex = new float[] {
- 1f, 1f, 0f, //V0
- -1f, 1f, 0f, //V1
- -1f, -1f, 0f, //V2
- 1f, -1f, 0f //V3
- };
- float[] texture = {
- 1f, 0f, //V0
- 0f, 0f, //V1
- 0f, 1.0f, //V2
- 1f, 1.0f //V3
- };
- vertexBuffer = mGLUtils.getFloatBuffer(vertex);
- textureBuffer = mGLUtils.getFloatBuffer(texture);
- }
- }
复制代码 MyGLUtils.java- package com.zhyan8.egldemo;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.opengl.GLES30;
- import android.opengl.GLUtils;
- import java.io.BufferedReader;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.nio.ByteBuffer;
- import java.nio.ByteOrder;
- import java.nio.FloatBuffer;
- public class MyGLUtils {
- private Context mContext;
- private Bitmap mBitmap;
- public MyGLUtils(Context context) {
- mContext = context;
- }
- public FloatBuffer getFloatBuffer(float[] floatArr) {
- FloatBuffer fb = ByteBuffer.allocateDirect(floatArr.length * Float.BYTES)
- .order(ByteOrder.nativeOrder())
- .asFloatBuffer();
- fb.put(floatArr);
- fb.position(0);
- return fb;
- }
- //通过代码片段编译着色器
- public int compileShader(int type, String shaderCode){
- int shader = GLES30.glCreateShader(type);
- GLES30.glShaderSource(shader, shaderCode);
- GLES30.glCompileShader(shader);
- return shader;
- }
- //通过外部资源编译着色器
- public int compileShader(int type, int shaderId){
- String shaderCode = readShaderFromResource(shaderId);
- return compileShader(type, shaderCode);
- }
- //链接到着色器
- public int linkProgram(int vertexShaderId, int fragmentShaderId) {
- final int programId = GLES30.glCreateProgram();
- //将顶点着色器加入到程序
- GLES30.glAttachShader(programId, vertexShaderId);
- //将片元着色器加入到程序
- GLES30.glAttachShader(programId, fragmentShaderId);
- //链接着色器程序
- GLES30.glLinkProgram(programId);
- return programId;
- }
- //从shader文件读出字符串
- private String readShaderFromResource(int shaderId) {
- InputStream is = mContext.getResources().openRawResource(shaderId);
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String line;
- StringBuilder sb = new StringBuilder();
- try {
- while ((line = br.readLine()) != null) {
- sb.append(line);
- sb.append("\n");
- }
- br.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return sb.toString();
- }
- //加载纹理贴图
- public int loadTexture(int resourceId) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inScaled = false;
- mBitmap = BitmapFactory.decodeResource(mContext.getResources(), resourceId, options);
- final int[] textureIds = new int[1];
- // 生成纹理id
- GLES30.glGenTextures(1, textureIds, 0);
- // 绑定纹理到OpenGL
- GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0]);
- GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);
- GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
- // 加载bitmap到纹理中
- GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, mBitmap, 0);
- // 生成MIP贴图
- GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);
- // 取消绑定纹理
- GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
- return textureIds[0];
- }
- }
复制代码 vertex_shader.glsl- attribute vec4 a_position;
- attribute vec2 a_texCoord;
- varying vec2 v_texCoord;
- void main() {
- gl_Position = a_position;
- v_texCoord = a_texCoord;
- }
复制代码 fragment_shader.glsl- precision mediump float;
- uniform sampler2D u_texture;
- varying vec2 v_texCoord;
- void main() {
- gl_FragColor = texture2D(u_texture, v_texCoord);
- }
复制代码 运行效果如下。
3 继承 TextureView 方案
自定义一个 View 继承 TextureView,并实现 TextureView.SurfaceTextureListener 接口,在 onSurfaceTextureAvailable 方法中会提供 SurfaceTexture,我们可以创建一个 Surface,并将 SurfaceTexture 传给 Surface,然后将创建的 Surface 传给 eglCreateWindowSurface 函数。
前段时间在看 Rive 的源码,详见 → rive-android源码分析,了解到 Rive 底层是通过 OpenGL ES 渲染图像,并且也没有使用 GLSurfaceView,由此借鉴而来。该方案主要参考 Rive 中 RiveTextureView 的实现,eglCreateWindowSurface 参考 thread_state_egl.cpp。
与第二节相比,只有 EGLSurfaceView 类有差异,因此本节仅展示 EGLSurfaceView 的代码。
EGLSurfaceView.java- package com.zhyan8.egldemo;
- import android.content.Context;
- import android.graphics.SurfaceTexture;
- import android.opengl.EGL14;
- import android.opengl.EGLConfig;
- import android.opengl.EGLContext;
- import android.opengl.EGLDisplay;
- import android.opengl.EGLExt;
- import android.opengl.EGLSurface;
- import android.util.Log;
- import android.view.Choreographer;
- import android.view.Surface;
- import android.view.TextureView;
- import androidx.annotation.NonNull;
- /**
- * @author little fat sheep
- * 承载EGL环境的View, 类比GLSurfaceView
- */
- public class EGLSurfaceView extends TextureView implements TextureView.SurfaceTextureListener {
- private static final String TAG = "EGLSurfaceView";
- protected EGLDisplay mEGLDisplay;
- protected EGLConfig mEGLConfig;
- protected EGLContext mEGLContext;
- protected EGLSurface mEGLSurface;
- protected Context mContext;
- protected Surface mSurface;
- protected Renderer mRenderer;
- private Choreographer mChoreographer = Choreographer.getInstance();
- public EGLSurfaceView(Context context) {
- super(context);
- mContext = context;
- setSurfaceTextureListener(this);
- }
- // 设置渲染器
- public void setRenderer(Renderer renderer) {
- mRenderer = renderer;
- }
- // 开始持续渲染
- public void startRender() {
- Log.i(TAG, "startRender");
- mChoreographer.removeFrameCallback(mFrameCallback);
- mChoreographer.postFrameCallback(mFrameCallback);
- }
- // 暂停持续渲染
- public void stopRender() {
- Log.i(TAG, "stopRender");
- mChoreographer.removeFrameCallback(mFrameCallback);
- }
- // 请求渲染一帧
- public void requestRender() {
- mFrameCallback.doFrame(System.nanoTime());
- }
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Log.i(TAG, "onAttachedToWindow");
- createDisplay();
- createConfig();
- createContext();
- }
- @Override
- public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
- Log.i(TAG, "onSurfaceTextureAvailable");
- mSurface = new Surface(surface);
- createSurface();
- makeCurrent();
- mRenderer.onSurfaceCreated();
- mRenderer.onSurfaceChanged(width, height);
- }
- @Override
- public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
- Log.i(TAG, "onSurfaceTextureSizeChanged, width=" + width + ", height=" + height);
- mRenderer.onSurfaceChanged(width, height);
- }
- @Override
- public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
- Log.i(TAG, "onSurfaceTextureDestroyed");
- return false;
- }
- @Override
- public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
- }
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Log.i(TAG, "onDetachedFromWindow");
- stopRender();
- setSurfaceTextureListener(null);
- mSurface.release();
- if (mEGLDisplay != null && mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- // 与显示设备解绑
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- // 销毁 EGLSurface
- if (mEGLSurface != null && mEGLSurface != EGL14.EGL_NO_SURFACE) {
- EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
- checkoutConfig("eglDestroySurface");
- mEGLSurface = null;
- }
- // 销毁 EGLContext
- if (mEGLContext != null && mEGLContext != EGL14.EGL_NO_CONTEXT) {
- EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
- checkoutConfig("eglDestroyContext");
- mEGLContext = null;
- }
- // 销毁 EGLDisplay (显示设备)
- EGL14.eglTerminate(mEGLDisplay);
- checkoutConfig("eglTerminate");
- mEGLDisplay = null;
- }
- }
- // 1.创建EGLDisplay
- private void createDisplay() {
- mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- int[] versions = new int[2];
- EGL14.eglInitialize(mEGLDisplay, versions,0, versions, 1);
- checkoutConfig("eglInitialize");
- }
- // 2.创建EGLConfig
- private void createConfig() {
- if (mEGLDisplay != null && mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- EGLConfig[] configs = new EGLConfig[1];
- int[] configNum = new int[1];
- EGL14.eglChooseConfig(mEGLDisplay, mEGLConfigAttrs, 0, configs, 0,1, configNum, 0);
- if (configNum[0] > 0) {
- mEGLConfig = configs[0];
- }
- checkoutConfig("eglChooseConfig");
- }
- }
- // 3.创建EGLContext
- private void createContext() {
- if (mEGLConfig != null) {
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, mEGLConfig, EGL14.EGL_NO_CONTEXT, mEGLContextAttrs, 0);
- checkoutConfig("eglCreateContext");
- }
- }
- // 4.创建EGLSurface
- private void createSurface() {
- if (mEGLContext != null && mEGLContext != EGL14.EGL_NO_CONTEXT) {
- int[] eglSurfaceAttrs = { EGL14.EGL_NONE };
- mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mSurface, eglSurfaceAttrs, 0);
- checkoutConfig("eglCreateWindowSurface");
- }
- }
- // 5.绑定EGLSurface和EGLContext到显示设备(EGLDisplay)
- private void makeCurrent() {
- if (mEGLSurface != null && mEGLSurface != EGL14.EGL_NO_SURFACE) {
- EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
- checkoutConfig("eglMakeCurrent");
- }
- }
- private void checkoutConfig(String tag) {
- int error = EGL14.eglGetError();
- if (error != EGL14.EGL_SUCCESS) {
- Log.e(TAG, tag + " error=0x" + Integer.toHexString(error));
- }
- }
- // EGLConfig参数
- private int[] mEGLConfigAttrs = {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_ALPHA_SIZE, 8,
- EGL14.EGL_DEPTH_SIZE, 8,
- //EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
- EGL14.EGL_RENDERABLE_TYPE, EGLExt.EGL_OPENGL_ES3_BIT_KHR,
- EGL14.EGL_NONE
- };
- // EGLContext参数
- private int[] mEGLContextAttrs = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 3,
- EGL14.EGL_NONE
- };
- Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
- @Override
- public void doFrame(long frameTimeNanos) {
- mChoreographer.postFrameCallback(mFrameCallback);
- if (mEGLSurface != null) {
- mRenderer.onDrawFrame();
- EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
- checkoutConfig("eglSwapBuffers");
- }
- }
- };
- /**
- * @author little fat sheep
- * 渲染器接口, 类比GLSurfaceView.Renderer
- */
- interface Renderer {
- void onSurfaceCreated();
- void onSurfaceChanged(int width, int height);
- void onDrawFrame();
- }
- }
复制代码 运行效果如下。
声明:本文转自【OpenGL ES】不用GLSurfaceView,如何渲染图像。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |