一、自定義GLSurfaceView
- 繼成SurfaceView,並實現其CallBack回調
- 自定義GLThread線程類,主要用於OpenGL的繪製操作
- 添加設置Surface和EglContext的方法
- 提供和系統GLSurfaceView相同的調用方法
二、代碼使用
1、自定義MyEGLSurfaceView
public class MyEGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private Surface surface;
private EGLContext eglContext;
private MyEGLThread mEGLThread;
private MyGLRender mGLRender;
public final static int RENDERMODE_WHEN_DIRTY = 0;
//自動模式:GL線程以一 定的時間間隔自動的循環調用用戶實現的onDrawFrame()方法進行一幀一幀的繪製
public final static int RENDERMODE_CONTINUOUSLY = 1;
//"髒"模式 也就是說當用戶需要重繪的時候,主動 “拉”這個重繪過程,有點類似於Canvas中的invalidate(),一般情況下使用髒模式,這樣可以有效降低cpu負載
private int mRenderMode = RENDERMODE_CONTINUOUSLY;
public MyEGLSurfaceView(Context context) {
this(context, null);
}
public MyEGLSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyEGLSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
getHolder().addCallback(this);
}
public void setRender(MyGLRender mGLRender) {
this.mGLRender = mGLRender;
}
//設置模式
public void setRenderMode(int mRenderMode) {
if(mGLRender == null)
{
throw new RuntimeException("must set render before");
}
this.mRenderMode = mRenderMode;
}
public void setSurfaceAndEglContext(Surface surface, EGLContext eglContext)
{
this.surface = surface;
this.eglContext = eglContext;
}
//獲取EglContext上下文
public EGLContext getEglContext()
{
if(mEGLThread != null)
{
return mEGLThread.getEglContext();
}
return null;
}
//當需要重繪時,調用requestRender()方法
public void requestRender()
{
if(mEGLThread != null)
{
mEGLThread.requestRender();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(surface == null)
{
surface = holder.getSurface();
}
//開啓一個線程處理EGL
mEGLThread = new MyEGLThread(new WeakReference<MyEGLSurfaceView>(this));
mEGLThread.isCreate = true;
mEGLThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mEGLThread.width = width;
mEGLThread.height = height;
mEGLThread.isChange = true;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mEGLThread.onDestory();
mEGLThread = null;
surface = null;
eglContext = null;
}
public interface MyGLRender
{
void onSurfaceCreated();
void onSurfaceChanged(int width, int height);
void onDrawFrame();
}
//自定義MyEGLThread線程類,主要用於OpenGL的繪製操作
static class MyEGLThread extends Thread{
private WeakReference<MyEGLSurfaceView> meglSurfaceViewWeakReference;
private EglHelper eglHelper = null;
private Object object = null;
private boolean isExit = false;
private boolean isCreate = false;
private boolean isChange = false;
private boolean isStart = false;
private int width;
private int height;
public MyEGLThread(WeakReference<MyEGLSurfaceView> meglSurfaceViewWeakReference) {
this.meglSurfaceViewWeakReference = meglSurfaceViewWeakReference;
}
@Override
public void run() {
super.run();
isExit = false;
isStart = false;
object = new Object();
eglHelper = new EglHelper();
eglHelper.initEgl(meglSurfaceViewWeakReference.get().surface, meglSurfaceViewWeakReference.get().eglContext);
while (true)
{
if(isExit)
{
//釋放資源
release();
break;
}
if(isStart)
{
if(meglSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_WHEN_DIRTY)
{
synchronized (object)
{
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
else if(meglSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_CONTINUOUSLY)
{
try {
Thread.sleep(1000 / 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else
{
throw new RuntimeException("mRenderMode is wrong value");
}
}
onCreate();
onChange(width, height);
onDraw();
isStart = true;
}
}
private void onCreate()
{
if(isCreate && meglSurfaceViewWeakReference.get().mGLRender != null)
{
isCreate = false;
meglSurfaceViewWeakReference.get().mGLRender.onSurfaceCreated();
}
}
private void onChange(int width, int height)
{
if(isChange && meglSurfaceViewWeakReference.get().mGLRender != null)
{
isChange = false;
meglSurfaceViewWeakReference.get().mGLRender.onSurfaceChanged(width, height);
}
}
private void onDraw()
{
if(meglSurfaceViewWeakReference.get().mGLRender != null && eglHelper != null)
{
meglSurfaceViewWeakReference.get().mGLRender.onDrawFrame();
if(!isStart)
{
meglSurfaceViewWeakReference.get().mGLRender.onDrawFrame();
}
eglHelper.swapBuffers();
}
}
private void requestRender()
{
if(object != null)
{
synchronized (object)
{
object.notifyAll();
}
}
}
public void onDestory()
{
isExit = true;
requestRender();
}
public void release()
{
if(eglHelper != null)
{
eglHelper.destoryEgl();
eglHelper = null;
object = null;
meglSurfaceViewWeakReference = null;
}
}
public EGLContext getEglContext()
{
if(eglHelper != null)
{
return eglHelper.getmEglContext();
}
return null;
}
}
}
2、創建一個MyRender類實現MyEGLSurfaceView.MyGLRender
public class MyRender implements MyEGLSurfaceView.MyGLRender{
private static final String TAG = "wq892373445";
public MyRender(){}
@Override
public void onSurfaceCreated() {
Log.d(TAG, "onSurfaceCreated");
}
@Override
public void onSurfaceChanged(int width, int height) {
GLES20.glViewport(0, 0, width, height);
Log.d(TAG, "onSurfaceChanged");
}
@Override
public void onDrawFrame() {
Log.d(TAG, "onDrawFrame");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
}
}
3、繼承MyGlSurfaceView
public class MyGlSurfaceView extends MyEGLSurfaceView{
public MyGlSurfaceView(Context context) {
this(context, null);
}
public MyGlSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyGlSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setRender(new MyRender());
setRenderMode(MyEGLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
4、佈局文件中使用
<com.wq.myglsurfaceview.MyGlSurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent" />
最後效果如下: