MyGLSurfaceView
package com.example.opengldemo;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.annotation.NonNull;
import java.lang.ref.WeakReference;
import javax.microedition.khronos.egl.EGLContext;
public abstract class MyGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Surface surface;
private EGLContext eglContext;
private MyGLThread myGLThread;
private MyGLRender myGLRender;
public static final int RENDERMODE_WHEN_DIRTY = 0;
public static final int RENDERMODE_CONTINUOUSLY = 1;
public int mRenderMode = RENDERMODE_CONTINUOUSLY;
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);
getHolder().addCallback(this);
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
myGLThread.width = width;
myGLThread.height = height;
myGLThread.isChange = true;
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
myGLThread.onDestory();
myGLThread = null;
surface = null;
eglContext = null;
}
@Override
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
if(surface == null){
surface = surfaceHolder.getSurface();
}
myGLThread = new MyGLThread(new WeakReference<MyGLSurfaceView>(this));
myGLThread.isCreate = true;
myGLThread.start();
}
public void setSurfaceAndEglContext(Surface surface,EGLContext eglContext){
this.surface = surface;
this.eglContext = eglContext;
}
public EGLContext getEglContext(){
if(myGLThread!=null){
return myGLThread.getEglContext();
}
return null;
}
public void requestRender(){
if (myGLThread != null){
myGLThread.requestRnder();
}
}
public void setMyGLRender(MyGLRender myGLRender) {
this.myGLRender = myGLRender;
}
public void setmRenderMode(int mRenderMode) {
if(myGLRender ==null){
throw new RuntimeException("must set render before");
}
this.mRenderMode = mRenderMode;
}
public interface MyGLRender{
void onSufaceCreated();
void onSufaceChanged(int width,int height);
void onDrawFrame();
}
static class MyGLThread extends Thread{
private WeakReference<MyGLSurfaceView> myGLSurfaceViewWeakReference;
private MyEglHelper myEglHelper = null;
private boolean isExit = false;
private boolean isCreate = false;
private boolean isChange = false;
private boolean isStart = false;
private Object object = null;
private int width;
private int height;
public MyGLThread(WeakReference<MyGLSurfaceView> myGLSurfaceViewWeakReference) {
this.myGLSurfaceViewWeakReference = myGLSurfaceViewWeakReference;
}
@Override
public void run() {
super.run();
isExit = false;
isStart = false;
object = new Object();
myEglHelper = new MyEglHelper();
myEglHelper.initEgl(myGLSurfaceViewWeakReference.get().surface,
myGLSurfaceViewWeakReference.get().eglContext);
while (true){
if(isExit){
release();
break;
}
if(isStart){
if(myGLSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_WHEN_DIRTY){
synchronized (object){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}else if (myGLSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_CONTINUOUSLY){
try {
Thread.sleep(1000/60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
throw new RuntimeException("mRenderMode is error value");
}
}
onCreate();
onChange(width, height);
onDraw();
isStart = true;
}
}
private void onCreate(){
if (isCreate &&myGLSurfaceViewWeakReference.get().myGLRender != null){
isCreate = false;
myGLSurfaceViewWeakReference.get().myGLRender.onSufaceCreated();
}
}
private void onChange(int width,int height){
if(isChange && myGLSurfaceViewWeakReference.get().myGLRender != null){
isChange = false;
myGLSurfaceViewWeakReference.get().myGLRender.onSufaceChanged(width, height);
}
}
private void onDraw(){
if(myGLSurfaceViewWeakReference.get().myGLRender != null &&myEglHelper != null){
myGLSurfaceViewWeakReference.get().myGLRender.onDrawFrame();
if(!isStart){
myGLSurfaceViewWeakReference.get().myGLRender.onDrawFrame();
}
myEglHelper.swapBuffers();
}
}
private void requestRnder(){
if(object != null){
synchronized (object){
object.notifyAll();
}
}
}
public void release(){
if(myEglHelper != null){
myEglHelper.destoryEgl();
myEglHelper = null;
object = null;
myGLSurfaceViewWeakReference = null;
}
}
public void onDestory(){
isExit = true;
requestRnder();
}
public EGLContext getEglContext(){
if(myEglHelper!=null){
return myEglHelper.getmEglContext();
}
return null;
}
}
}
编写GGlSurfaceView继承上面这个类
package com.example.opengldemo;
import android.content.Context;
import android.util.AttributeSet;
public class GGlSurfaceView extends MyGLSurfaceView{
public GGlSurfaceView(Context context) {
this(context,null);
}
public GGlSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public GGlSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setMyGLRender(new MyRender());
}
}
写Render
package com.example.opengldemo;
import android.opengl.GLES20;
public class MyRender implements MyGLSurfaceView.MyGLRender {
public MyRender() {
}
@Override
public void onSufaceCreated() {
}
@Override
public void onSufaceChanged(int width, int height) {
GLES20.glViewport(0,0,width,height);
}
@Override
public void onDrawFrame() {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
}
}
activity EglSurfaceActivity
package com.example.opengldemo;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class EglSurfaceActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_egl);
}
}