package com.example.datalibrary.deptrum.openglhelper;
|
|
import android.opengl.EGL14;
|
import android.opengl.EGLExt;
|
import android.util.Log;
|
import android.view.SurfaceHolder;
|
import android.view.SurfaceView;
|
|
import javax.microedition.khronos.egl.EGL10;
|
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLContext;
|
import javax.microedition.khronos.egl.EGLDisplay;
|
import javax.microedition.khronos.egl.EGLSurface;
|
|
/**
|
* @author
|
*/
|
public abstract class BaseOpenglRenderThread extends Thread implements SurfaceHolder.Callback {
|
protected String tAG = BaseOpenglRenderThread.class.getSimpleName();
|
|
public BaseOpenglRenderThread(String name, SurfaceView mSurfaceView) {
|
super(name);
|
this.mSurfaceView = mSurfaceView;
|
this.mSurfaceView.getHolder().addCallback(this);
|
}
|
|
@Override
|
public void run() {
|
super.run();
|
isRunning = true;
|
synchronized (this) {
|
while (!isSurfaceValid) {
|
try {
|
wait();
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
if (!isRunning) {
|
return;
|
}
|
// 初始化环境
|
prepareEgl();
|
creatProgram();
|
// 开始绘制
|
while (isRunning) {
|
synchronized (mRendLock) {
|
try {
|
mRendLock.wait();
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
if (!isRunning) {
|
break;
|
}
|
// TODO绘制
|
draw();
|
mEGL10.eglSwapBuffers(mEGLDisplay, mEGLSurface);
|
}
|
}
|
releaseEgl();
|
}
|
|
protected abstract void creatProgram();
|
|
protected abstract void draw();
|
|
protected void notifyDraw() {
|
synchronized (mRendLock) {
|
mRendLock.notifyAll();
|
}
|
}
|
|
/**
|
* 初始化egl opengl环境
|
*
|
* @throws
|
*/
|
private void prepareEgl() {
|
mEGL10 = (EGL10) EGLContext.getEGL();
|
checkSurfaceView();
|
mEGLDisplay = mEGL10.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
|
if (EGL10.EGL_NO_DISPLAY == mEGLDisplay) {
|
throw new RuntimeException("eglGetDisplay faile");
|
}
|
int[] majorMinor = new int[2];
|
if (!mEGL10.eglInitialize(mEGLDisplay, majorMinor)) {
|
throw new RuntimeException("eglInitialize faile");
|
}
|
int[] attribs =
|
filterConfigSpec(
|
new int[]{
|
EGL10.EGL_RED_SIZE, 8,
|
EGL10.EGL_GREEN_SIZE, 8,
|
EGL10.EGL_BLUE_SIZE, 8,
|
EGL10.EGL_ALPHA_SIZE, hasAlpha ? 8 : 0,
|
EGL10.EGL_DEPTH_SIZE, 0,
|
EGL10.EGL_STENCIL_SIZE, 0,
|
EGL10.EGL_NONE
|
});
|
|
EGLConfig[] eglConfigs = new EGLConfig[1];
|
int[] numConfig = new int[1];
|
if (!mEGL10.eglChooseConfig(mEGLDisplay, attribs, eglConfigs, 1, numConfig)) {
|
throw new RuntimeException("eglChooseConfig faile");
|
}
|
EGLConfig eglConfig = eglConfigs[0];
|
// 4、配置opengl上下文环境
|
int[] contextAttribs = {0x3098, 2, EGL10.EGL_NONE};
|
mEGLContext =
|
mEGL10.eglCreateContext(mEGLDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, contextAttribs);
|
if (mEGLContext == null) {
|
throw new RuntimeException("eglCreateContext faile");
|
}
|
mEGLSurface =
|
mEGL10.eglCreateWindowSurface(mEGLDisplay, eglConfig, mSurfaceView.getHolder(), null);
|
if (mEGLSurface == null || mEGLSurface == EGL10.EGL_NO_SURFACE) {
|
int error = mEGL10.eglGetError();
|
if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
|
Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
|
}
|
}
|
if (!mEGL10.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
|
throw new RuntimeException("eglMakeCurrent faile");
|
}
|
}
|
|
/**
|
* 释放资源
|
*/
|
private void releaseEgl() {
|
if (mEGL10 != null && mEGLDisplay != null) {
|
mEGL10.eglMakeCurrent(
|
mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
|
if (mEGLSurface != null) {
|
mEGL10.eglDestroySurface(mEGLDisplay, mEGLSurface);
|
}
|
if (mEGLContext != null) {
|
mEGL10.eglDestroyContext(mEGLDisplay, mEGLContext);
|
}
|
mEGL10.eglTerminate(mEGLDisplay);
|
}
|
}
|
|
private int[] filterConfigSpec(int[] configSpec) {
|
if (mEGLContextClientVersion != 2 && mEGLContextClientVersion != 3) {
|
return configSpec;
|
}
|
|
int len = configSpec.length;
|
int[] newConfigSpec = new int[len + 2];
|
System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1);
|
newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE;
|
if (mEGLContextClientVersion == 2) {
|
newConfigSpec[len] = EGL14.EGL_OPENGL_ES2_BIT; /* EGL_OPENGL_ES2_BIT */
|
} else {
|
newConfigSpec[len] = EGLExt.EGL_OPENGL_ES3_BIT_KHR; /* EGL_OPENGL_ES3_BIT_KHR */
|
}
|
newConfigSpec[len + 1] = EGL10.EGL_NONE;
|
return newConfigSpec;
|
}
|
|
public void setEGLContextClientVersion(int version) {
|
mEGLContextClientVersion = version;
|
}
|
|
private void checkSurfaceView() {
|
if (mSurfaceView == null) {
|
throw new RuntimeException("surfaceview can not be null");
|
}
|
}
|
|
@Override
|
public void surfaceCreated(SurfaceHolder holder) {
|
isSurfaceValid = true;
|
synchronized (this) {
|
notifyAll();
|
}
|
}
|
|
@Override
|
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
}
|
|
@Override
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
}
|
|
private int mEGLContextClientVersion;
|
/**
|
* 渲染目标
|
*/
|
private SurfaceView mSurfaceView;
|
|
private EGL10 mEGL10;
|
|
private EGLSurface mEGLSurface;
|
|
private EGLDisplay mEGLDisplay;
|
|
private EGLContext mEGLContext;
|
|
private EGLConfig mEGLConfig;
|
|
private volatile boolean isRunning = false;
|
|
public void setRunning(boolean running) {
|
isRunning = running;
|
synchronized (this) {
|
notifyAll();
|
}
|
synchronized (mRendLock) {
|
mRendLock.notifyAll();
|
}
|
}
|
|
private Object mRendLock = new Object();
|
|
private volatile boolean isSurfaceValid = false;
|
|
protected boolean hasAlpha = false;
|
|
public void setHasAlpha(boolean hasAlpha) {
|
this.hasAlpha = hasAlpha;
|
}
|
}
|