GLView与GLES20崩溃

时间:2013-12-09 20:21:47

标签: java android opengl-es

在我的应用中,我有这个错误:

logcat的:

E/AndroidRuntime(23121): FATAL EXCEPTION: main
E/AndroidRuntime(23121): java.lang.ClassCastException: com.google.android.gles_jni.EGLImpl cannot be cast to javax.microedition.khronos.egl.EGL11
E/AndroidRuntime(23121):    at it.hidden.math.GLView.initGL(GLView.java:103)
E/AndroidRuntime(23121):    at it.hidden.math.GLView.surfaceChanged(GLView.java:168)
E/AndroidRuntime(23121):    at it.hidden.math.Graph3dView.surfaceChanged(Graph3dView.java:1)
E/AndroidRuntime(23121):    at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
E/AndroidRuntime(23121):    at android.view.SurfaceView.access$000(SurfaceView.java:86)
E/AndroidRuntime(23121):    at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:174)
E/AndroidRuntime(23121):    at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:680)
E/AndroidRuntime(23121):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1842)
E/AndroidRuntime(23121):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
E/AndroidRuntime(23121):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
E/AndroidRuntime(23121):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
E/AndroidRuntime(23121):    at android.view.Choreographer.doCallbacks(Choreographer.java:562)
E/AndroidRuntime(23121):    at android.view.Choreographer.doFrame(Choreographer.java:532)
E/AndroidRuntime(23121):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
E/AndroidRuntime(23121):    at android.os.Handler.handleCallback(Handler.java:725)
E/AndroidRuntime(23121):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(23121):    at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(23121):    at android.app.ActivityThread.main(ActivityThread.java:5227)
E/AndroidRuntime(23121):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(23121):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(23121):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
E/AndroidRuntime(23121):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
E/AndroidRuntime(23121):    at dalvik.system.NativeStart.main(Native Method)

这是GLView类中的代码:

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import android.content.Context;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Handler;
import android.os.Message;
import android.graphics.Bitmap;

abstract class GLView extends GLSurfaceView implements SurfaceHolder.Callback {
private boolean hasSurface;
private boolean paused;
private EGL11 egl;
private EGLDisplay display;
private EGLConfig config;    
private EGLSurface surface;
private EGLContext eglContext;
private GLES20 gl;
protected int width, height;
private boolean mIsLooping;

abstract void onDrawFrame(GLES20 gl2);
abstract void onSurfaceCreated(GLES20 gl2, int width, int height);

public String captureScreenshot() {
    Bitmap bitmap = getRawPixels(gl, width, height);
    Util.bitmapBGRtoRGB(bitmap, width, height);
    return Util.saveBitmap(bitmap, Grapher.SCREENSHOT_DIR, "calculator");
}

private static Bitmap getRawPixels(GLES20 gl2, int width, int height) {
    int size = width * height;
    ByteBuffer buf = ByteBuffer.allocateDirect(size * 4);
    buf.order(ByteOrder.nativeOrder());
    gl2.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buf);
    int data[] = new int[size];
    buf.asIntBuffer().get(data);
    buf = null;
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    bitmap.setPixels(data, size-width, -width, 0, 0, width, height);
    return bitmap;
}

private Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        glDraw();

    }
};

public GLView(Context context) {
    super(context);
    setEGLContextClientVersion(2);
    init();
}


public GLView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setEGLContextClientVersion(2);

    init();
}

private void init() {
    SurfaceHolder holder = getHolder();
    holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
    setEGLContextClientVersion(2);

    holder.addCallback(this);
}

public void onResume() {
    Calculator.log("onResume " + this);
    paused = false;
    if (hasSurface) {
        initGL();
    }
}

public void onPause() {
    Calculator.log("onPause " + this);
    deinitGL();
}

private void initGL() {
    egl = (EGL11) EGLContext.getEGL();
    display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);       
    int[] ver = new int[2];
    egl.eglInitialize(display, ver);

    int[] configSpec = {EGL10.EGL_NONE};
    EGLConfig[] configOut = new EGLConfig[1];
    int[] nConfig = new int[1];
    egl.eglChooseConfig(display, configSpec, configOut, 1, nConfig);

    config = configOut[0];

    eglContext = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, null);
    surface = egl.eglCreateWindowSurface(display, config, getHolder(), null);
    egl.eglMakeCurrent(display, surface, surface, eglContext);
    gl = (GLES20) eglContext.getGL();
    onSurfaceCreated(gl, width, height);
    requestDraw();
}


private void deinitGL() {
    paused = true;
    if (display != null) {
        egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
        egl.eglDestroySurface(display, surface);
        egl.eglDestroyContext(display, eglContext);
        egl.eglTerminate(display);

        egl = null;
        config = null;
        eglContext = null;
        surface = null;
        display = null;
        gl = null;
    }
}

protected void glDraw() {
    if (hasSurface && !paused) {
        onDrawFrame(gl);
        if (!egl.eglSwapBuffers(display, surface)) {
            Calculator.log("swapBuffers error " + egl.eglGetError());
        }
        if (egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) {
            Calculator.log("egl context lost " + this);
            paused = true;
        }
        if (mIsLooping) {
            requestDraw();
        }
    }
}

public void surfaceCreated(SurfaceHolder holder) {
    Calculator.log("surfaceCreated " + this);
}

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    Calculator.log("surfaceChanged " + format + ' ' + this);
    this.width  = width;
    this.height = height;
    boolean doInit = !hasSurface && !paused;
    hasSurface = true;
    if (doInit) {
        initGL();
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    Calculator.log("surfaceDestroyed " + this);
    hasSurface = false;
    deinitGL();
}

public void startLooping() {
    if (!mIsLooping) {
        Calculator.log("start looping");
        mIsLooping = true;
        glDraw();
    }
}

public void stopLooping() {
    if (mIsLooping) {
        Calculator.log("stop looping");
        mIsLooping = false;
    }
}

public boolean isLooping() {
    return mIsLooping;
}

public void requestDraw() {
    handler.sendEmptyMessage(1);
}
}

我遇到所有这些问题时,我已经将此说明包括在内:

Android:hardwareAccelerated =" true"

之前我发布了另一个问题,因为它给了我以下错误的应用程序:

称为未实现的OpenGL ES API

然后我改变了GLView.class尝试使用GLES20,但我发现自己在这个问题中发布了logcat

老问题: Called unimplemented OpenGL ES API Android

1 个答案:

答案 0 :(得分:0)

我不确定你是否理解在android中实现OpenGL的基础知识。

您无需对SurfaceHolder执行任何操作。您只需要调用GLSurfaceView的setRenderer()方法,并传递一个实现Renderer接口的类。查看this链接以获取更多信息。你也应该查看android示例。

如果您想使用GLES20,那么您从不将拥有GLES20类实例,您正在使用静态调用来操作曲面。 You can find those calls in the GLES20 class.还要确保在使用其中一个Renderer类回调方法时只调用这些方法。

还要确保使用android.opengl。* package中的类。