From patchwork Thu Sep 29 08:13:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: alexandros.frantzis@linaro.org X-Patchwork-Id: 4421 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 30FFC23F57 for ; Thu, 29 Sep 2011 08:13:18 +0000 (UTC) Received: from mail-fx0-f52.google.com (mail-fx0-f52.google.com [209.85.161.52]) by fiordland.canonical.com (Postfix) with ESMTP id 1979BA1804B for ; Thu, 29 Sep 2011 08:13:18 +0000 (UTC) Received: by fxe23 with SMTP id 23so2184381fxe.11 for ; Thu, 29 Sep 2011 01:13:18 -0700 (PDT) Received: by 10.223.57.17 with SMTP id a17mr1486349fah.65.1317283997895; Thu, 29 Sep 2011 01:13:17 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.3.234 with SMTP id f10cs7024laf; Thu, 29 Sep 2011 01:13:17 -0700 (PDT) Received: by 10.216.229.138 with SMTP id h10mr732516weq.90.1317283996591; Thu, 29 Sep 2011 01:13:16 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id n47si585437wed.125.2011.09.29.01.13.16 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 29 Sep 2011 01:13:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) smtp.mail=bounces@canonical.com Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1R9Bk3-0007Q7-Tq for ; Thu, 29 Sep 2011 08:13:15 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id D48F6E180D for ; Thu, 29 Sep 2011 08:13:15 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: glmark2 X-Launchpad-Branch: ~glmark2-dev/glmark2/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 147 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~glmark2-dev/glmark2/trunk] Rev 147: Android: Use a custom EGLConfigChooser that gracefully handles eglChooseConfig failures. Message-Id: <20110929081315.7661.76023.launchpad@ackee.canonical.com> Date: Thu, 29 Sep 2011 08:13:15 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="14063"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: a79984cf203676dd1ec56fdba9baceafe3ced5b5 ------------------------------------------------------------ revno: 147 fixes bug: https://launchpad.net/bugs/851334 committer: Alexandros Frantzis branch nick: lp-851334 timestamp: Wed 2011-09-28 18:48:47 +0300 message: Android: Use a custom EGLConfigChooser that gracefully handles eglChooseConfig failures. When proper GLES2.0 drivers are missing from an Android device, eglChooseConfig() will fail to find a GLES2.0 capable config, as expected. Unfortunately, the default EGLConfigChooser implementation doesn't give us a chance to handle this error; it throws an exception that we cannot catch (because it comes from an internal thread) and crashes the application. In order to handle the error gracefully, this commit introduces a custom EGLConfigChooser implementation that in case of error displays an informative alert and then quits the application. modified: android/src/org/linaro/glmark2/Glmark2Activity.java android/src/org/linaro/glmark2/Glmark2SurfaceView.java --- lp:glmark2 https://code.launchpad.net/~glmark2-dev/glmark2/trunk You are subscribed to branch lp:glmark2. To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription === modified file 'android/src/org/linaro/glmark2/Glmark2Activity.java' --- android/src/org/linaro/glmark2/Glmark2Activity.java 2011-08-12 10:18:18 +0000 +++ android/src/org/linaro/glmark2/Glmark2Activity.java 2011-09-28 15:48:47 +0000 @@ -3,8 +3,13 @@ import android.app.Activity; import android.os.Bundle; import android.opengl.GLSurfaceView; +import android.app.Dialog; +import android.app.AlertDialog; +import android.content.DialogInterface; public class Glmark2Activity extends Activity { + public static final int DIALOG_EGLCONFIG_FAIL_ID = 0; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -24,6 +29,38 @@ mGLView.onResume(); } + @Override + protected Dialog onCreateDialog(int id) { + Dialog dialog; + switch (id) { + case DIALOG_EGLCONFIG_FAIL_ID: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage("Glmark2 cannot run because it couldn't find a suitable EGLConfig for GLES2.0. Please check that proper GLES2.0 drivers are installed."); + builder.setCancelable(false); + builder.setPositiveButton("Quit", + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Glmark2Activity.this.finish(); + /* + * Force process shutdown. There is no safer way to + * do this, as we have open threads we can't close + * when we fail to get an EGLConfig + */ + android.os.Process.killProcess(android.os.Process.myPid()); + } + }); + + dialog = builder.create(); + break; + default: + dialog = null; + break; + } + + return dialog; + } + + private GLSurfaceView mGLView; static { === modified file 'android/src/org/linaro/glmark2/Glmark2SurfaceView.java' --- android/src/org/linaro/glmark2/Glmark2SurfaceView.java 2011-08-12 10:15:46 +0000 +++ android/src/org/linaro/glmark2/Glmark2SurfaceView.java 2011-09-28 15:48:47 +0000 @@ -6,6 +6,8 @@ import android.content.res.AssetManager; import android.app.Activity; +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; @@ -19,11 +21,125 @@ // Uncomment the commands below to get an RGBA8888 surface and config. //this.getHolder().setFormat(PixelFormat.TRANSLUCENT); - //setEGLConfigChooser(8, 8, 8, 8, 16, 0); + //setEGLConfigChooser(new Glmark2ConfigChooser(8, 8, 8, 8, 16, 0)); + setEGLConfigChooser(new Glmark2ConfigChooser(5, 6, 5, 0, 16, 0)); setRenderer(new Glmark2Renderer(this)); } + /** + * EGLConfigChooser that quits with an error dialog when a suitable config + * cannot be found. + */ + private class Glmark2ConfigChooser implements EGLConfigChooser { + private int[] mAttribList; + + public Glmark2ConfigChooser(int redSize, int greenSize, int blueSize, + int alphaSize, int depthSize, int stencilSize) + { + mAttribList = new int[] { + EGL10.EGL_RED_SIZE, redSize, + EGL10.EGL_GREEN_SIZE, greenSize, + EGL10.EGL_BLUE_SIZE, blueSize, + EGL10.EGL_ALPHA_SIZE, alphaSize, + EGL10.EGL_DEPTH_SIZE, depthSize, + EGL10.EGL_STENCIL_SIZE, stencilSize, + EGL10.EGL_RENDERABLE_TYPE, 4, /* 4 = EGL_OPENGL_ES2_BIT */ + EGL10.EGL_NONE }; + mRedSize = redSize; + mGreenSize = greenSize; + mBlueSize = blueSize; + mAlphaSize = alphaSize; + mDepthSize = depthSize; + mStencilSize = stencilSize; + } + + @Override + public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { + try { + return chooseConfigInternal(egl, display); + } + catch (Exception e) { + /* Display an informative (and lethal for the app) dialog */ + mActivity.runOnUiThread(new Runnable() { + public void run() { + mActivity.showDialog(Glmark2Activity.DIALOG_EGLCONFIG_FAIL_ID); + } + }); + + /* Wait here until the app process gets killed... */ + synchronized (this) { + try { this.wait(); } catch (Exception ex) { } + } + } + return null; + } + + private EGLConfig chooseConfigInternal(EGL10 egl, EGLDisplay display) { + /* Get the number of available configs matching the attributes */ + int[] num_config = new int[1]; + if (!egl.eglChooseConfig(display, mAttribList, null, 0, num_config)) { + throw new IllegalArgumentException("eglChooseConfig failed"); + } + + int numConfigs = num_config[0]; + + if (numConfigs <= 0) { + throw new IllegalArgumentException("No matching configs found"); + } + + /* Get the matching configs */ + EGLConfig[] configs = new EGLConfig[numConfigs]; + if (!egl.eglChooseConfig(display, mAttribList, configs, numConfigs, + num_config)) + { + throw new IllegalArgumentException("eglChooseConfig#2 failed"); + } + + /* + * Try to find a config that matches exactly the RGBA size + * specified by the user and is >= for depth and stencil. + */ + for (EGLConfig config : configs) { + int d = findConfigAttrib(egl, display, config, + EGL10.EGL_DEPTH_SIZE, 0); + int s = findConfigAttrib(egl, display, config, + EGL10.EGL_STENCIL_SIZE, 0); + 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); + if (r == mRedSize && g == mGreenSize && + b == mBlueSize && a == mAlphaSize && + d >= mDepthSize && s >= mStencilSize) + { + return config; + } + } + + throw new IllegalArgumentException("No configs match exactly"); + } + + private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, + int attribute, int defaultValue) + { + int[] value = new int[] { defaultValue }; + egl.eglGetConfigAttrib(display, config, attribute, value); + return value[0]; + } + + protected int mRedSize; + protected int mGreenSize; + protected int mBlueSize; + protected int mAlphaSize; + protected int mDepthSize; + protected int mStencilSize; + } + public Activity getActivity() { return mActivity; }