铁岭市网站建设_网站建设公司_SEO优化_seo优化
2025/12/18 0:30:34 网站建设 项目流程

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);

}

​ 运行效果如下。

img

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();

}

}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询