();
+
+ for (Limit limit : Limits)
+ {
+ Log.i("GLInfoFragment", "Getting enum " + limit.name);
+ Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
+ }
+
+ // Get extensions manually
+ int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS);
+ StringBuilder extensionsBuilder = new StringBuilder();
+ for (int i = 0; i < numExtensions; i++)
+ {
+ extensionsBuilder.append(eglHelper.glGetStringi(GL10.GL_EXTENSIONS, i)).append('\n');
+ }
+ Input.add(new AboutActivity.AboutFragmentItem("OpenGL Extensions", extensionsBuilder.toString()));
+
+ AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
+ rootView.setAdapter(adapter);
+
+ return rootView;
+ }
+}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java
new file mode 100644
index 0000000000..96b206b837
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java
@@ -0,0 +1,65 @@
+package org.dolphinemu.dolphinemu.about;
+
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
+final class Limit
+{
+ /**
+ * Possible types a Limit can be.
+ */
+ enum Type
+ {
+ /** Generic string */
+ STRING,
+ /** Integer constant */
+ INTEGER,
+ /** Range of integers */
+ INTEGER_RANGE,
+ }
+
+ /** Name of this limit */
+ public final String name;
+ /** The GL constant that represents this limit.*/
+ public final int glEnum;
+ /** The {@link Type} of this limit. */
+ public final Type type;
+
+ /**
+ * Constructor
+ *
+ * @param name Name of the limit.
+ * @param glEnum The GL constant that represents this limit.
+ * @param type The {@link Type} of this limit.
+ */
+ public Limit(String name, int glEnum, Type type)
+ {
+ this.name = name;
+ this.glEnum = glEnum;
+ this.type = type;
+ }
+
+ /**
+ * Retrieves the information represented by this limit.
+ *
+ * @param context {@link EGLHelper} context to retrieve the limit with.
+ *
+ * @return the information represented by this limit.
+ */
+ public String GetValue(EGLHelper context)
+ {
+ if (type == Type.INTEGER)
+ {
+ return Integer.toString(context.glGetInteger(glEnum));
+ }
+ else if (type == Type.INTEGER_RANGE)
+ {
+ int[] data = new int[2];
+ context.getGL().glGetIntegerv(glEnum, data, 0);
+
+ return String.format("[%d, %d]", data[0], data[1]);
+ }
+
+ // If neither of the above type, assume it's a string.
+ return context.glGetString(glEnum);
+ }
+}
\ No newline at end of file
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
index f04bf77e4e..7f6896536c 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
@@ -22,10 +22,12 @@ import android.view.WindowManager.LayoutParams;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.settings.input.InputConfigFragment;
-import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
import java.util.List;
+import javax.microedition.khronos.opengles.GL10;
+
/**
* This is the activity where all of the emulation handling happens.
* This activity is responsible for displaying the SurfaceView that we render to.
@@ -65,11 +67,7 @@ public final class EmulationActivity extends Activity
// This bug is fixed in Qualcomm driver v53
// Mali isn't affected by this bug.
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
- if (sharedPrefs.getString("gpuPref", "Software Rendering").equals("OGL")
- && VideoSettingsFragment.SupportsGLES3()
- && VideoSettingsFragment.m_GLVendor != null
- && VideoSettingsFragment.m_GLVendor.equals("Qualcomm")
- && VideoSettingsFragment.m_QualcommVersion < 53.0f)
+ if (hasBuggedDriverDimensions())
NativeLibrary.SetDimensions((int)screenHeight, (int)screenWidth);
else
NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight);
@@ -330,4 +328,39 @@ public final class EmulationActivity extends Activity
return true;
}
+
+ // For handling bugged driver dimensions (applies mainly to Qualcomm devices)
+ private boolean hasBuggedDriverDimensions()
+ {
+ final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+ final String vendor = eglHelper.getGL().glGetString(GL10.GL_VENDOR);
+ final String version = eglHelper.getGL().glGetString(GL10.GL_VERSION);
+ final String renderer = eglHelper.getGL().glGetString(GL10.GL_RENDERER);
+
+ if (sharedPrefs.getString("gpuPref", "Software Rendering").equals("OGL")
+ && eglHelper.supportsGLES3()
+ && vendor.equals("Qualcomm")
+ && renderer.equals("Adreno (TM) 3"))
+ {
+ final int start = version.indexOf("V@") + 2;
+ final StringBuilder versionBuilder = new StringBuilder();
+
+ for (int i = start; i < version.length(); i++)
+ {
+ char c = version.charAt(i);
+
+ // End of numeric portion of version string.
+ if (c == ' ')
+ break;
+
+ versionBuilder.append(c);
+ }
+
+ if (Float.parseFloat(versionBuilder.toString()) < 53.0f)
+ return true;
+ }
+
+
+ return false;
+ }
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
index 85fa9a62da..6a5f806da4 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
@@ -23,9 +23,10 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
-import org.dolphinemu.dolphinemu.AboutFragment;
+
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.about.AboutActivity;
import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowser;
import org.dolphinemu.dolphinemu.settings.PrefsActivity;
import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter;
@@ -119,11 +120,7 @@ public final class GameListActivity extends Activity
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.device_compat_warning);
builder.setMessage(R.string.device_compat_warning_msg);
- builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- // Do Nothing. Just create the Yes button
- }
- });
+ builder.setPositiveButton(R.string.yes, null);
builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
@@ -184,13 +181,8 @@ public final class GameListActivity extends Activity
case 3: // About
{
- mCurFragmentNum = 3;
- final AboutFragment aboutFragment = new AboutFragment();
- FragmentTransaction ft = getFragmentManager().beginTransaction();
- ft.replace(R.id.content_frame, aboutFragment);
- ft.addToBackStack(null);
- ft.commit();
- invalidateOptionsMenu();
+ Intent intent = new Intent(this, AboutActivity.class);
+ startActivity(intent);
}
break;
@@ -261,7 +253,8 @@ public final class GameListActivity extends Activity
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.clear_game_list);
builder.setMessage(getString(R.string.clear_game_list_confirm));
- builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener(){
+ builder.setNegativeButton(R.string.no, null);
+ builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which)
{
String directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0");
@@ -279,12 +272,6 @@ public final class GameListActivity extends Activity
((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList();
}
});
- builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which)
- {
- // Do nothing. This just make "No" appear.
- }
- });
builder.show();
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
index 5368475319..41979ece46 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
@@ -41,7 +41,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen
super.onCreate(savedInstanceState);
// Set the ViewPager.
- setContentView(R.layout.prefs_viewpager);
+ setContentView(R.layout.viewpager);
mViewPager = (ViewPager) findViewById(R.id.pager);
// Set the ViewPager adapter.
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
index f36a7d3ec7..55c1eb8963 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
@@ -15,9 +15,10 @@ import android.preference.ListPreference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import org.dolphinemu.dolphinemu.R;
-import javax.microedition.khronos.egl.*;
+import org.dolphinemu.dolphinemu.R;
+import org.dolphinemu.dolphinemu.utils.EGLHelper;
+
import javax.microedition.khronos.opengles.GL10;
/**
@@ -25,173 +26,9 @@ import javax.microedition.khronos.opengles.GL10;
*/
public final class VideoSettingsFragment extends PreferenceFragment
{
- public static String m_GLVersion;
- public static String m_GLVendor;
- public static String m_GLRenderer;
- public static String m_GLExtensions;
- public static boolean m_SupportsGLES3 = false;
- public static float m_QualcommVersion;
- public static boolean m_Inited = false;
-
- /**
- * Class which provides a means to retrieve various
- * info about the OpenGL ES support/features within a device.
- */
- public static final class VersionCheck
- {
- private EGL10 mEGL;
- private EGLDisplay mEGLDisplay;
- private EGLConfig[] mEGLConfigs;
- private EGLConfig mEGLConfig;
- private EGLContext mEGLContext;
- private EGLSurface mEGLSurface;
- private GL10 mGL;
-
- String mThreadOwner;
-
- public VersionCheck()
- {
- int[] version = new int[2];
- int[] attribList = new int[] {
- EGL10.EGL_WIDTH, 1,
- EGL10.EGL_HEIGHT, 1,
- EGL10.EGL_RENDERABLE_TYPE, 4,
- EGL10.EGL_NONE
- };
- int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
- int[] ctx_attribs = new int[] {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL10.EGL_NONE
- };
-
- // No error checking performed, minimum required code to elucidate logic
- mEGL = (EGL10) EGLContext.getEGL();
- mEGLDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
- mEGL.eglInitialize(mEGLDisplay, version);
- mEGLConfig = chooseConfig(); // Choosing a config is a little more complicated
- mEGLContext = mEGL.eglCreateContext(mEGLDisplay, mEGLConfig, EGL10.EGL_NO_CONTEXT, ctx_attribs);
- mEGLSurface = mEGL.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, attribList);
- mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
- mGL = (GL10) mEGLContext.getGL();
-
- // Record thread owner of OpenGL context
- mThreadOwner = Thread.currentThread().getName();
- }
-
- /**
- * Gets the OpenGL ES version string.
- *
- * @return the OpenGL ES version string.
- */
- public String getVersion()
- {
- return mGL.glGetString(GL10.GL_VERSION);
- }
-
- /**
- * Gets the OpenGL ES vendor string.
- *
- * @return the OpenGL ES vendor string.
- */
- public String getVendor()
- {
- return mGL.glGetString(GL10.GL_VENDOR);
- }
-
- /**
- * Gets the name of the OpenGL ES renderer.
- *
- * @return the name of the OpenGL ES renderer.
- */
- public String getRenderer()
- {
- return mGL.glGetString(GL10.GL_RENDERER);
- }
-
- /**
- * Gets the extension that the device supports
- *
- * @return String containing the extensions
- */
- public String getExtensions()
- {
- return mGL.glGetString(GL10.GL_EXTENSIONS);
- }
-
- private EGLConfig chooseConfig()
- {
- int[] attribList = new int[] {
- EGL10.EGL_RED_SIZE, 8,
- EGL10.EGL_GREEN_SIZE, 8,
- EGL10.EGL_BLUE_SIZE, 8,
- EGL10.EGL_ALPHA_SIZE, 8,
- EGL10.EGL_NONE
- };
-
- // Grab how many configs there are
- int[] numConfig = new int[1];
- mEGL.eglChooseConfig(mEGLDisplay, attribList, null, 0, numConfig);
- int configSize = numConfig[0];
- mEGLConfigs = new EGLConfig[configSize];
- mEGL.eglChooseConfig(mEGLDisplay, attribList, mEGLConfigs, configSize, numConfig);
-
- // Check if one config supports GLES3
- for (int i = 0; i < configSize; ++i)
- {
- int[] value = new int[1];
- boolean retval = mEGL.eglGetConfigAttrib(mEGLDisplay, mEGLConfigs[i], EGL10.EGL_RENDERABLE_TYPE, value);
- if (retval && (value[0] & (1 << 6)) != 0)
- {
- m_SupportsGLES3 = true;
- break;
- }
- }
-
- return mEGLConfigs[0]; // Best match is probably the first configuration
- }
- }
-
- /**
- * Checks if this device supports OpenGL ES 3.
- *
- * @return true if this device supports OpenGL ES 3; false otherwise.
- */
- public static boolean SupportsGLES3()
- {
- if (!m_Inited)
- {
- VersionCheck mbuffer = new VersionCheck();
- m_GLVersion = mbuffer.getVersion();
- m_GLVendor = mbuffer.getVendor();
- m_GLRenderer = mbuffer.getRenderer();
- m_GLExtensions = mbuffer.getExtensions();
-
- // Checking for OpenGL ES 3 support for certain Qualcomm devices.
- if (m_GLVendor != null && m_GLVendor.equals("Qualcomm"))
- {
- if (m_GLRenderer.contains("Adreno (TM) 3"))
- {
- int mVStart = m_GLVersion.indexOf("V@") + 2;
- int mVEnd = 0;
-
- for (int a = mVStart; a < m_GLVersion.length(); ++a)
- {
- if (m_GLVersion.charAt(a) == ' ')
- {
- mVEnd = a;
- break;
- }
- }
-
- m_QualcommVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd));
- }
- }
-
- m_Inited = true;
- }
-
- return m_SupportsGLES3;
- }
+ private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
+ private final String vendor = eglHelper.getGL().glGetString(GL10.GL_VENDOR);
+ private final String version = eglHelper.getGL().glGetString(GL10.GL_VERSION);
@Override
public void onCreate(Bundle savedInstanceState)
@@ -205,7 +42,7 @@ public final class VideoSettingsFragment extends PreferenceFragment
// Setting valid video backends.
//
final ListPreference videoBackends = (ListPreference) findPreference("gpuPref");
- final boolean deviceSupportsGLES3 = SupportsGLES3();
+ final boolean deviceSupportsGLES3 = eglHelper.supportsGLES3();
if (deviceSupportsGLES3)
{
@@ -264,10 +101,9 @@ public final class VideoSettingsFragment extends PreferenceFragment
//mainScreen.getPreference(4).setEnabled(false);
// Create an alert telling them that their phone sucks
- if (VideoSettingsFragment.SupportsGLES3()
- && VideoSettingsFragment.m_GLVendor != null
- && VideoSettingsFragment.m_GLVendor.equals("Qualcomm")
- && VideoSettingsFragment.m_QualcommVersion == 14.0f)
+ if (eglHelper.supportsGLES3()
+ && vendor.equals("Qualcomm")
+ && getQualcommVersion() == 14.0f)
{
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.device_compat_warning);
@@ -295,4 +131,23 @@ public final class VideoSettingsFragment extends PreferenceFragment
}
});
}
+
+ private float getQualcommVersion()
+ {
+ final int start = version.indexOf("V@") + 2;
+ final StringBuilder versionBuilder = new StringBuilder();
+
+ for (int i = start; i < version.length(); i++)
+ {
+ char c = version.charAt(i);
+
+ // End of numeric portion of version string.
+ if (c == ' ')
+ break;
+
+ versionBuilder.append(c);
+ }
+
+ return Float.parseFloat(versionBuilder.toString());
+ }
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java
new file mode 100644
index 0000000000..43e6b66da4
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java
@@ -0,0 +1,400 @@
+package org.dolphinemu.dolphinemu.utils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.dolphinemu.dolphinemu.R;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+/**
+ * Utility class for retrieving information
+ * from a device's CPU.
+ */
+public final class CPUHelper
+{
+ private int revision;
+ private int architecture;
+ private int variant;
+ private int numCores;
+ private String implementerID = "N/A";
+ private String part = "N/A";
+ private String hardware = "N/A";
+ private String processorInfo = "N/A";
+ private String features = "N/A";
+
+ private final Context ctx;
+
+ /**
+ * Constructor
+ *
+ * @param ctx The current {@link Context}.
+ */
+ public CPUHelper(Context ctx)
+ {
+ this.ctx = ctx;
+
+ try
+ {
+ // TODO: Should do other architectures as well (x86 and MIPS).
+ // Can do differentiating between platforms by using
+ // android.os.Build.CPU_ABI.
+ //
+ // CPU_ABI.contains("armeabi") == get ARM info.
+ // CPU_ABI.contains("x86") == get x86 info.
+ // CPU_ABI.contains("mips") == get MIPS info.
+ //
+ // However additional testing should be done across devices,
+ // I highly doubt /proc/cpuinfo retains the same formatting
+ // on different architectures.
+ //
+ // If push comes to shove, we can simply spit out the cpuinfo
+ // contents. I would like to avoid this if possible, however.
+
+ if (Build.CPU_ABI.contains("arm"))
+ {
+ getARMInfo();
+ }
+ else
+ {
+ Log.e("CPUHelper", "CPU architecture not supported yet.");
+ }
+ }
+ catch (IOException ioe)
+ {
+ Log.e("CPUHelper", ioe.getMessage());
+ }
+ }
+
+ /**
+ * Gets the revision number of the CPU.
+ *
+ * @return the revision number of the CPU.
+ */
+ public int getRevision()
+ {
+ return revision;
+ }
+
+ /**
+ * Gets the architecture number of the CPU.
+ *
+ * @return the architecture number of the CPU.
+ */
+ public int getArchitecture()
+ {
+ return architecture;
+ }
+
+ /**
+ * Gets the CPU variant number.
+ *
+ * @return the CPU variant number.
+ */
+ public int getVariant()
+ {
+ return variant;
+ }
+
+ /**
+ * Gets the total number of cores in the CPU.
+ *
+ * @return the total number of cores in the CPU.
+ */
+ public int getNumCores()
+ {
+ return numCores;
+ }
+
+ /**
+ * Gets the name of the implementer of the CPU.
+ *
+ * @return the name of the implementer of the CPU.
+ */
+ public String getImplementer()
+ {
+ return implementerID;
+ }
+
+ /**
+ * Gets the specific processor type of the CPU.
+ *
+ * @return the specific processor type.
+ */
+ public String getProcessorType()
+ {
+ return part;
+ }
+
+ /**
+ * Gets the internal name of the hardware.
+ *
+ * @return the internal name of the hardware.
+ */
+ public String getHardware()
+ {
+ return hardware;
+ }
+
+ /**
+ * Get the processor info string.
+ *
+ * @return the processor info string.
+ */
+ public String getProcessorInfo()
+ {
+ return processorInfo;
+ }
+
+ /**
+ * Gets the features supported by the CPU.
+ *
+ * @return the features supported by the CPU.
+ */
+ public String getFeatures()
+ {
+ return features;
+ }
+
+ /**
+ * Whether or not this CPU is using the ARM architecture.
+ *
+ * @return true if this CPU uses the ARM architecture; false otherwise.
+ */
+ public static boolean isARM()
+ {
+ return Build.CPU_ABI.contains("arm");
+ }
+
+ /**
+ * Whether or not this CPU is using the x86 architecture.
+ *
+ * @return true if this CPU uses the x86 architecture; false otherwise.
+ */
+ public static boolean isX86()
+ {
+ return Build.CPU_ABI.contains("x86");
+ }
+
+ /**
+ * Whether or not this CPU is using the MIPS architecture.
+ *
+ * @return true if this CPU uses the MIPS architecture; false otherwise.
+ */
+ public static boolean isMIPS()
+ {
+ return Build.CPU_ABI.contains("mips");
+ }
+
+ // Retrieves information for ARM CPUs.
+ private void getARMInfo() throws IOException
+ {
+ File info = new File("/proc/cpuinfo");
+ if (info.exists())
+ {
+ BufferedReader br = new BufferedReader(new FileReader(info));
+
+ String line;
+ while ((line = br.readLine()) != null)
+ {
+ if (line.contains("Processor\t:"))
+ {
+ this.processorInfo = parseLine(line);
+ }
+ else if (line.contains("Hardware\t:"))
+ {
+ this.hardware = parseLine(line);
+ }
+ else if (line.contains("Features\t:"))
+ {
+ this.features = parseLine(line);
+ }
+ else if (line.contains("CPU implementer\t:"))
+ {
+ this.implementerID = parseArmID(Integer.decode(parseLine(line)));
+ }
+ // Intentional lack of "\t:" sometimes the tab isn't present.
+ else if (line.contains("CPU architecture"))
+ {
+ this.architecture = Integer.decode(parseLine(line));
+ }
+ else if (line.contains("CPU part\t:"))
+ {
+ this.part = parseArmPartNumber(Integer.decode(parseLine(line)));
+ }
+ else if (line.contains("CPU revision\t:"))
+ {
+ this.revision = Integer.decode(parseLine(line));
+ }
+ else if (line.contains("CPU variant\t:"))
+ {
+ this.variant = Integer.decode(parseLine(line));
+ }
+ else if (line.contains("processor\t:")) // Lower case indicates a specific core number
+ {
+ this.numCores++;
+ }
+ }
+
+ br.close();
+ }
+ }
+
+ // Basic function for parsing cpuinfo format strings.
+ // cpuinfo format strings consist of [label:info] parts.
+ // We only want to retrieve the info portion so we split
+ // them using ':' as a delimeter.
+ private String parseLine(String line)
+ {
+ String[] temp = line.split(":");
+ if (temp.length != 2)
+ return "N/A";
+
+ return temp[1].trim();
+ }
+
+ // Parses an ARM CPU ID.
+ private String parseArmID(int id)
+ {
+ switch (id)
+ {
+ case 0x41:
+ return "ARM Limited";
+
+ case 0x44:
+ return "Digital Equipment Corporation";
+
+ case 0x4D:
+ return "Freescale Semiconductor Inc.";
+
+ case 0x51:
+ return "Qualcomm Inc.";
+
+ case 0x56:
+ return "Marvell Semiconductor Inc.";
+
+ case 0x69:
+ return "Intel Corporation";
+
+ default:
+ return "N/A";
+ }
+ }
+
+ // Parses the ARM CPU Part number.
+ private String parseArmPartNumber(int partNum)
+ {
+ switch (partNum)
+ {
+ // Qualcomm part numbers.
+ case 0x00F:
+ return "Qualcomm Scorpion";
+
+ case 0x02D:
+ return "Qualcomm Dual Scorpion";
+
+ case 0x04D:
+ return "Qualcomm Dual Krait";
+
+ case 0x06F:
+ return "Qualcomm Quad Krait";
+
+ // Marvell Semiconductor part numbers
+ case 0x131:
+ return "Marvell Feroceon";
+
+ case 0x581:
+ return "Marvell PJ4/PJ4b";
+
+ case 0x584:
+ return "Marvell Dual PJ4/PJ4b";
+
+ // Official ARM part numbers.
+ case 0x920:
+ return "ARM920";
+
+ case 0x922:
+ return "ARM922";
+
+ case 0x926:
+ return "ARM926";
+
+ case 0x940:
+ return "ARM940";
+
+ case 0x946:
+ return "ARM946";
+
+ case 0x966:
+ return "ARM966";
+
+ case 0x968:
+ return "ARM968";
+
+ case 0xB02:
+ return "ARM11 MPCore";
+
+ case 0xB36:
+ return "ARM1136";
+
+ case 0xB56:
+ return "ARM1156";
+
+ case 0xB76:
+ return "ARM1176";
+
+ case 0xC05:
+ return "ARM Cortex A5";
+
+ case 0xC07:
+ return "ARM Cortex-A7 MPCore";
+
+ case 0xC08:
+ return "ARM Cortex A8";
+
+ case 0xC09:
+ return "ARM Cortex A9";
+
+ case 0xC0C:
+ return "ARM Cortex A12";
+
+ case 0xC0F:
+ return "ARM Cortex A15";
+
+ case 0xC14:
+ return "ARM Cortex R4";
+
+ case 0xC15:
+ return "ARM Cortex R5";
+
+ case 0xC20:
+ return "ARM Cortex M0";
+
+ case 0xC21:
+ return "ARM Cortex M1";
+
+ case 0xC23:
+ return "ARM Cortex M3";
+
+ case 0xC24:
+ return "ARM Cortex M4";
+
+ case 0xC60:
+ return "ARM Cortex M0+";
+
+ case 0xD03:
+ return "ARM Cortex A53";
+
+ case 0xD07:
+ return "ARM Cortex A57 MPCore";
+
+
+ default: // Unknown/Not yet added to list.
+ return String.format(ctx.getString(R.string.unknown_part_num), partNum);
+ }
+ }
+}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java
new file mode 100644
index 0000000000..94ea903ae6
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java
@@ -0,0 +1,360 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.utils;
+
+import javax.microedition.khronos.egl.EGL10;
+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 android.opengl.GLES30;
+import android.util.Log;
+
+/**
+ * Utility class that abstracts all the stuff about
+ * EGL initialization out of the way if all that is
+ * wanted is to query the underlying GL API for information.
+ */
+public final class EGLHelper
+{
+ private final EGL10 mEGL;
+ private final EGLDisplay mDisplay;
+ private EGLConfig[] mEGLConfigs;
+ private EGLContext mEGLContext;
+ private EGLSurface mEGLSurface;
+ private GL10 mGL;
+
+ // GL support flags
+ private boolean supportGL;
+ private boolean supportGLES2;
+ private boolean supportGLES3;
+
+ // Renderable type bitmasks
+ public static final int EGL_OPENGL_ES_BIT = 0x0001;
+ public static final int EGL_OPENGL_ES2_BIT = 0x0004;
+ public static final int EGL_OPENGL_BIT = 0x0008;
+ public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
+
+ /**
+ * Constructor
+ *
+ * Initializes the underlying {@link EGLSurface} with a width and height of 1.
+ * This is useful if all you need to use this class for is to query information
+ * from specific API contexts.
+ *
+ * @param renderableType Bitmask indicating which types of client API contexts
+ * the framebuffer config must support.
+ */
+ public EGLHelper(int renderableType)
+ {
+ this(1, 1, renderableType);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param width Width of the underlying {@link EGLSurface}.
+ * @param height Height of the underlying {@link EGLSurface}.
+ * @param renderableType Bitmask indicating which types of client API contexts
+ * the framebuffer config must support.
+ */
+ public EGLHelper(int width, int height, int renderableType)
+ {
+ // Initialize handle to an EGL display.
+ mEGL = (EGL10) EGLContext.getEGL();
+ mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ // If a display is present, initialize EGL.
+ if (mDisplay != EGL10.EGL_NO_DISPLAY)
+ {
+ int[] version = new int[2];
+ if (mEGL.eglInitialize(mDisplay, version))
+ {
+ // Detect supported GL APIs, initialize configs, etc.
+ detect();
+
+ // Create context and surface
+ create(width, height, renderableType);
+ }
+ else
+ {
+ Log.e("EGLHelper", "Error initializing EGL.");
+ }
+ }
+ else
+ {
+ Log.e("EGLHelper", "Error initializing EGL display.");
+ }
+ }
+
+ /**
+ * Releases all resources associated with this helper.
+ *
+ * This should be called whenever this helper is no longer needed.
+ */
+ public void closeHelper()
+ {
+ mEGL.eglTerminate(mDisplay);
+ }
+
+ /**
+ * Gets information through EGL.
+ *
+ * Index 0: Vendor
+ * Index 1: Version
+ * Index 2: Renderer
+ * Index 3: Extensions
+ *
+ * @return information retrieved through EGL.
+ */
+ public String[] getEGLInfo()
+ {
+ String[] info = {
+ mGL.glGetString(GL10.GL_VENDOR),
+ mGL.glGetString(GL10.GL_VERSION),
+ mGL.glGetString(GL10.GL_RENDERER),
+ mGL.glGetString(GL10.GL_EXTENSIONS),
+ };
+
+ return info;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL.
+ *
+ * @return true if this device supports OpenGL; false otherwise.
+ */
+ public boolean supportsOpenGL()
+ {
+ return supportGL;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL ES 2.
+ *
+ * Note that if this returns true, then OpenGL ES 1 is also supported.
+ *
+ * @return true if this device supports OpenGL ES 2; false otherwise.
+ */
+ public boolean supportsGLES2()
+ {
+ return supportGLES2;
+ }
+
+ /**
+ * Whether or not this device supports OpenGL ES 3.
+ *
+ * Note that if this returns true, then OpenGL ES 1 and 2 are also supported.
+ *
+ * @return true if this device supports OpenGL ES 3; false otherwise.
+ */
+ public boolean supportsGLES3()
+ {
+ return supportGLES3;
+ }
+
+ /**
+ * Gets the underlying {@link EGL10} instance.
+ *
+ * @return the underlying {@link EGL10} instance.
+ */
+ public EGL10 getEGL()
+ {
+ return mEGL;
+ }
+
+ /**
+ * Gets the underlying {@link GL10} instance.
+ *
+ * @return the underlying {@link GL10} instance.
+ */
+ public GL10 getGL()
+ {
+ return mGL;
+ }
+
+ /**
+ * Gets the underlying {@link EGLDisplay}.
+ *
+ * @return the underlying {@link EGLDisplay}
+ */
+ public EGLDisplay getDisplay()
+ {
+ return mDisplay;
+ }
+
+ /**
+ * Gets all supported framebuffer configurations for this device.
+ *
+ * @return all supported framebuffer configurations for this device.
+ */
+ public EGLConfig[] getConfigs()
+ {
+ return mEGLConfigs;
+ }
+
+ /**
+ * Gets the underlying {@link EGLContext}.
+ *
+ * @return the underlying {@link EGLContext}.
+ */
+ public EGLContext getContext()
+ {
+ return mEGLContext;
+ }
+
+ /**
+ * Gets the underlying {@link EGLSurface}.
+ *
+ * @return the underlying {@link EGLSurface}.
+ */
+ public EGLSurface getSurface()
+ {
+ return mEGLSurface;
+ }
+
+ // Detects the specific kind of GL modes that are supported
+ private boolean detect()
+ {
+ // Get total number of configs available.
+ int[] numConfigs = new int[1];
+ if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs))
+ {
+ Log.e("EGLHelper", "Error retrieving number of EGL configs available.");
+ return false;
+ }
+
+ // Now get all the configurations
+ mEGLConfigs = new EGLConfig[numConfigs[0]];
+ if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs))
+ {
+ Log.e("EGLHelper", "Error retrieving all EGL configs.");
+ return false;
+ }
+
+ for (int i = 0; i < mEGLConfigs.length; i++)
+ {
+ int[] attribVal = new int[1];
+ boolean ret = mEGL.eglGetConfigAttrib(mDisplay, mEGLConfigs[i], EGL10.EGL_RENDERABLE_TYPE, attribVal);
+ if (ret)
+ {
+ if ((attribVal[0] & EGL_OPENGL_BIT) != 0)
+ supportGL = true;
+
+ if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0)
+ supportGLES2 = true;
+
+ if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0)
+ supportGLES3 = true;
+ }
+ }
+
+ return true;
+ }
+
+ // Creates the context and surface.
+ private void create(int width, int height, int renderableType)
+ {
+ int[] attribs = {
+ EGL10.EGL_WIDTH, width,
+ EGL10.EGL_HEIGHT, height,
+ EGL10.EGL_NONE
+ };
+
+ // Initially we just assume GLES2 will be the default context.
+ int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ int[] ctx_attribs = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL10.EGL_NONE
+ };
+
+ // Determine the type of context that will be created
+ // and change the attribute arrays accordingly.
+ switch (renderableType)
+ {
+ case EGL_OPENGL_ES_BIT:
+ ctx_attribs[1] = 1;
+ break;
+
+ case EGL_OPENGL_BIT:
+ ctx_attribs[0] = EGL10.EGL_NONE;
+ break;
+
+ case EGL_OPENGL_ES3_BIT_KHR:
+ ctx_attribs[1] = 3;
+ break;
+
+ case EGL_OPENGL_ES2_BIT:
+ default: // Fall-back to GLES 2.
+ ctx_attribs[1] = 2;
+ break;
+ }
+
+ mEGLContext = mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs);
+ mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs);
+ mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext);
+ mGL = (GL10) mEGLContext.getGL();
+ }
+
+ /**
+ * Simplified call to {@link GL10#glGetString(int)}
+ *
+ * Accepts the following constants:
+ *
+ * - GL_VENDOR - Company responsible for the GL implementation.
+ * - GL_VERSION - Version or release number.
+ * - GL_RENDERER - Name of the renderer
+ * - GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language
+ *
+ *
+ * @param glEnum A symbolic constant within {@link GL10}.
+ *
+ * @return the string information represented by {@code glEnum}.
+ */
+ public String glGetString(int glEnum)
+ {
+ return mGL.glGetString(glEnum);
+ }
+
+ /**
+ * Simplified call to {@link GLES30#glGetStringi(int, int)}
+ *
+ * Accepts the following constants:
+ *
+ * - GL_VENDOR - Company responsible for the GL implementation.
+ * - GL_VERSION - Version or release number.
+ * - GL_RENDERER - Name of the renderer
+ * - GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language
+ * - GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.
+ *
+ *
+ * @param glEnum A symbolic GL constant
+ * @param index The index of the string to return.
+ *
+ * @return the string information represented by {@code glEnum} and {@code index}.
+ */
+ public String glGetStringi(int glEnum, int index)
+ {
+ return GLES30.glGetStringi(glEnum, index);
+ }
+
+ /**
+ * Simplified call to {@link GL10#glGetIntegerv(int, int[], int)
+ *
+ * @param glEnum A symbolic GL constant.
+ *
+ * @return the integer information represented by {@code glEnum}.
+ */
+ public int glGetInteger(int glEnum)
+ {
+ int[] val = new int[1];
+ mGL.glGetIntegerv(glEnum, val, 0);
+ return val[0];
+ }
+}