11

androidのバージョンは2.2.1です。デバイスはsamsunggalaxyIIであり、完全なクラッシュログは次のとおりです。

java.lang.RuntimeException: createWindowSurface failed: EGL_BAD_MATCH
at android.opengl.GLSurfaceView$EglHelper.throwEglException(GLSurfaceView.java:1077)
at android.opengl.GLSurfaceView$EglHelper.createSurface(GLSurfaceView.java:981)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1304)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1116)

これは、クラッシュに関連するコードです。

@Override 
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                         WindowManager.LayoutParams.FLAG_FULLSCREEN);
    glView = new GLSurfaceView(this);
    glView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
    glView.setRenderer(this);
    setContentView(glView);
    \\etc..............}

setEGLConfigChooser()を使用したのは、API-17が存在しない場合、アプリがAPI-17でクラッシュするため、この特定のデバイスでクラッシュしているので、周りを見回していて、デバイスのPixelFormatと関係があります。

不思議に思うのは、サムスンギャラクシーII androidバージョン2.2.1でクラッシュしないようにコードを使用する方法です。エミュレータでこれをテストできず、テストするデバイスがありません。確かなコードが必要です。そしてそれを変更する方法がわかりませんか?

4

2 に答える 2

10

更新:この問題を回避する方法を見つけましたが、実際にはかなり簡単です。

まず第一に、Android のデフォルトのEGLConfigChooser実装は、一部のデバイスで不適切な決定を下します。特に古い Android デバイスでは、このEGL_BAD_MATCH問題が発生しているようです。デバッグ セッション中に、これらの古いトラブルメーカー デバイスで使用できる OpenGL ES 構成のセットが非常に限られていることも発見しました。

この「不適切な一致」の問題の原因は、GLSurfaceView のピクセル形式と OpenGL ES の色ビット深度設定との間の不一致だけではありません。全体として、次の問題に対処する必要があります。

  • OpenGL ES API バージョンの不一致
  • 要求されたターゲット サーフェス タイプの不一致
  • 要求された色のビット深度をサーフェス ビューでレンダリングできません

OpenGL ES API の説明に関しては、Android 開発者向けドキュメントが大幅に不足しています。したがって、Khronos.org で元のドキュメントを読むことが重要です。特に、ここではeglChooseConfigに関するドキュメント ページが役に立ちます。

上記の問題を解決するには、次の最小構成を指定する必要があります。

  • EGL_RENDERABLE_TYPE使用している OpenGL ES API のバージョンと一致する必要があります。OpenGL ES 2.x の場合、その属性を に設定する必要があります4(「 」を参照egl.h) 。
  • EGL_SURFACE_TYPEEGL_WINDOW_BITセットを持っている必要があります

もちろん、正しい色、深さ、およびステンシル バッファー設定を提供する OpenGL ES コンテキストもセットアップする必要があります。

残念ながら、これらの構成オプションを単純な方法で選択することはできません。特定のデバイスで利用できるものから選択する必要があります。EGLConfigChooserそのため、使用可能な構成セットのリストを調べて、指定された基準に最もよく一致する最適なものを選択するカスタムを実装する必要があります。

とにかく、私はそのような構成チューザーのサンプル実装を作成しました:

public class MyConfigChooser implements EGLConfigChooser {
    final private static String TAG = "MyConfigChooser";

    // This constant is not defined in the Android API, so we need to do that here:
    final private static int EGL_OPENGL_ES2_BIT = 4;

    // Our minimum requirements for the graphics context
    private static int[] mMinimumSpec = {
            // We want OpenGL ES 2 (or set it to any other version you wish)
            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

            // We want to render to a window
            EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,

            // We do not want a translucent window, otherwise the
            // home screen or activity in the background may shine through
            EGL10.EGL_TRANSPARENT_TYPE, EGL10.EGL_NONE, 

            // indicate that this list ends:
            EGL10.EGL_NONE
    };

    private int[] mValue = new int[1];
    protected int mAlphaSize;
    protected int mBlueSize;
    protected int mDepthSize;
    protected int mGreenSize;
    protected int mRedSize;
    protected int mStencilSize;

    /**
    * The constructor lets you specify your minimum pixel format,
    * depth and stencil buffer requirements.
    */
    public MyConfigChooser(int r, int g, int b, int a, int depth, int 
                        stencil) {
        mRedSize = r;
        mGreenSize = g;
        mBlueSize = b;
        mAlphaSize = a;
        mDepthSize = depth;
        mStencilSize = stencil;
    }

    @Override
    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
        int[] arg = new int[1];
        egl.eglChooseConfig(display, mMinimumSpec, null, 0, arg);
        int numConfigs = arg[0];
        Log.i(TAG, "%d configurations available", numConfigs);

        if(numConfigs <= 0) {
            // Ooops... even the minimum spec is not available here
            return null;
        }

        EGLConfig[] configs = new EGLConfig[numConfigs];
        egl.eglChooseConfig(display, mMinimumSpec, configs,    
            numConfigs, arg);

        // Let's do the hard work now (see next method below)
        EGLConfig chosen = chooseConfig(egl, display, configs);

        if(chosen == null) {
            throw new RuntimeException(
                    "Could not find a matching configuration out of "
                            + configs.length + " available.", 
                configs);
        }

        // Success
        return chosen;
    }

   /**
    * This method iterates through the list of configurations that 
    * fulfill our minimum requirements and tries to pick one that matches best
    * our requested color, depth and stencil buffer requirements that were set using 
    * the constructor of this class.
    */
    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
            EGLConfig[] configs) {
        EGLConfig bestMatch = null;
        int bestR = Integer.MAX_VALUE, bestG = Integer.MAX_VALUE, 
            bestB = Integer.MAX_VALUE, bestA = Integer.MAX_VALUE, 
            bestD = Integer.MAX_VALUE, bestS = Integer.MAX_VALUE;

        for(EGLConfig config : configs) {
            int r = findConfigAttrib(egl, display, config, 
                        EGL10.EGL_RED_SIZE, 0);
            int g = findConfigAttrib(egl, display, config,
                        EGL10.EGL_GREEN_SIZE, 0);
            int b = findConfigAttrib(egl, display, config,         
                        EGL10.EGL_BLUE_SIZE, 0);
            int a = findConfigAttrib(egl, display, config,
                    EGL10.EGL_ALPHA_SIZE, 0);
            int d = findConfigAttrib(egl, display, config,
                    EGL10.EGL_DEPTH_SIZE, 0);
            int s = findConfigAttrib(egl, display, config,
                    EGL10.EGL_STENCIL_SIZE, 0);

            if(r <= bestR && g <= bestG && b <= bestB && a <= bestA
                    && d <= bestD && s <= bestS && r >= mRedSize
                    && g >= mGreenSize && b >= mBlueSize 
                    && a >= mAlphaSize && d >= mDepthSize 
                    && s >= mStencilSize) {
                bestR = r;
                bestG = g;
                bestB = b;
                bestA = a;
                bestD = d;
                bestS = s;
                bestMatch = config;
            }
        }

        return bestMatch;
    }

    private int findConfigAttrib(EGL10 egl, EGLDisplay display,
            EGLConfig config, int attribute, int defaultValue) {

        if(egl.eglGetConfigAttrib(display, config, attribute, 
            mValue)) {
            return mValue[0];
        }

        return defaultValue;
    }
}
于 2013-08-11T08:06:38.873 に答える