From 45964e4b46475e772f6ed520083331a2568325d9 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 7 Jan 2014 19:47:15 -0500 Subject: [PATCH 1/9] [Android] Initial implementation of the extended info menu. Most fragments are not implemented yet. This is just a working base framework for it. --- Source/Android/AndroidManifest.xml | 1 + .../{prefs_viewpager.xml => viewpager.xml} | 0 Source/Android/res/values-ja/strings.xml | 4 + Source/Android/res/values/strings.xml | 5 + .../dolphinemu/about/AboutActivity.java | 151 ++++++++++++++++++ .../DolphinInfoFragment.java} | 16 +- .../dolphinemu/gamelist/GameListActivity.java | 27 +--- .../dolphinemu/settings/PrefsActivity.java | 2 +- 8 files changed, 178 insertions(+), 28 deletions(-) rename Source/Android/res/layout/{prefs_viewpager.xml => viewpager.xml} (100%) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java rename Source/Android/src/org/dolphinemu/dolphinemu/{AboutFragment.java => about/DolphinInfoFragment.java} (82%) diff --git a/Source/Android/AndroidManifest.xml b/Source/Android/AndroidManifest.xml index 80fb93470e..95d8b9a174 100644 --- a/Source/Android/AndroidManifest.xml +++ b/Source/Android/AndroidManifest.xml @@ -33,6 +33,7 @@ + ビルドのバージョン サポートのOpenGL ES 3 サポートのNEON + CPU + GLES 2 + GLES 3 + OpenGL 現在のディレクトリ: %1$s diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 3557261e66..b60a56e73c 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -12,6 +12,11 @@ Build Revision Supports OpenGL ES 3 Supports NEON + General + CPU + GLES 2 + GLES 3 + OpenGL Current Dir: %1$s diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java new file mode 100644 index 0000000000..c3f0f61af8 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -0,0 +1,151 @@ +package org.dolphinemu.dolphinemu.about; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment; + +import android.app.ActionBar; +import android.app.ActionBar.Tab; +import android.app.ActionBar.TabListener; +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.os.Bundle; +import android.support.v13.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; + +/** + * Activity for the about menu, which displays info + * related to the CPU and GPU. Along with misc other info. + */ +public final class AboutActivity extends Activity implements TabListener +{ + private ViewPager viewPager; + private boolean supportsGles3; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + // Set the view pager + setContentView(R.layout.viewpager); + viewPager = (ViewPager) findViewById(R.id.pager); + + // Check if GLES3 is supported + supportsGles3 = VideoSettingsFragment.SupportsGLES3(); + + // Initialize the ViewPager adapter. + final ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager()); + viewPager.setAdapter(adapter); + + // Set up the ActionBar + final ActionBar actionBar = getActionBar(); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + actionBar.addTab(actionBar.newTab().setText(R.string.general).setTabListener(this)); + actionBar.addTab(actionBar.newTab().setText(R.string.cpu).setTabListener(this)); + actionBar.addTab(actionBar.newTab().setText(R.string.gles_two).setTabListener(this)); + if (supportsGles3) + actionBar.addTab(actionBar.newTab().setText(R.string.gles_three).setTabListener(this)); + // TODO: Check if Desktop GL is possible before enabling. + actionBar.addTab(actionBar.newTab().setText(R.string.desktop_gl).setTabListener(this)); + + // Set the page change listener + viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() + { + @Override + public void onPageSelected(int position) + { + actionBar.setSelectedNavigationItem(position); + } + }); + } + + @Override + public void onTabSelected(Tab tab, FragmentTransaction ft) + { + // When the given tab is selected, switch to the corresponding page in the ViewPager. + viewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabReselected(Tab tab, FragmentTransaction ft) + { + // Do nothing. + } + + @Override + public void onTabUnselected(Tab tab, FragmentTransaction ft) + { + // Do nothing. + } + + /** + * {@link FragmentPagerAdapter} subclass responsible for handling + * the individual {@link Fragment}s within the {@link ViewPager}. + */ + private final class ViewPagerAdapter extends FragmentPagerAdapter + { + public ViewPagerAdapter(FragmentManager fm) + { + super(fm); + } + + @Override + public Fragment getItem(int position) + { + switch (position) + { + case 0: return new DolphinInfoFragment(); + // TODO: The rest of these fragments + case 1: return new Fragment(); // CPU + case 2: return new Fragment(); // GLES 2 + case 3: return new Fragment(); // GLES 3 + case 4: return new Fragment(); // Desktop GL + + default: // Should never happen + return null; + } + } + + @Override + public int getCount() + { + // TODO: In the future, make sure to take into account + // whether or not regular Desktop GL is possible. + if (supportsGles3) + { + return 5; + } + else + { + return 4; + } + } + + @Override + public CharSequence getPageTitle(int position) + { + switch (position) + { + case 0: + return getString(R.string.general); + + case 1: + return getString(R.string.cpu); + + case 2: + return getString(R.string.gles_two); + + case 3: + return getString(R.string.gles_three); + + case 4: + return getString(R.string.desktop_gl); + + default: // Should never happen + return null; + } + } + } +} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java similarity index 82% rename from Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java rename to Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java index 6ca90a2577..fccc20925f 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java @@ -4,7 +4,7 @@ * Refer to the license.txt file included. */ -package org.dolphinemu.dolphinemu; +package org.dolphinemu.dolphinemu.about; import android.app.ListFragment; import android.content.Context; @@ -19,12 +19,14 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.List; +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment; /** * Represents the about screen. */ -public final class AboutFragment extends ListFragment +public final class DolphinInfoFragment extends ListFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) @@ -39,14 +41,14 @@ public final class AboutFragment extends ListFragment Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); - AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input); + InfoFragmentAdapter adapter = new InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); rootView.setAdapter(adapter); rootView.setEnabled(false); // Makes the list view non-clickable. return rootView; } - // Represents an item in the AboutFragment. + // Represents an item in the DolphinInfoFragment. private static final class AboutFragmentItem { private final String title; @@ -69,14 +71,14 @@ public final class AboutFragment extends ListFragment } } - // The adapter that manages the displaying of items in this AboutFragment. - private static final class AboutFragmentAdapter extends ArrayAdapter + // The adapter that manages the displaying of items in this DolphinInfoFragment. + private static final class InfoFragmentAdapter extends ArrayAdapter { private final Context ctx; private final int id; private final List items; - public AboutFragmentAdapter(Context ctx, int id, List items) + public InfoFragmentAdapter(Context ctx, int id, List items) { super(ctx, id, items); 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. From f8abdbf91a9996a008a11c47e4a92334a323fc12 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 19 Jan 2014 18:29:43 -0500 Subject: [PATCH 2/9] [Android] Initial introduction of the EGLHelper utility class. Should simplify all interop with the EGL/GL APIs. Not hooked up yet. However it is entirely functional. --- .../dolphinemu/utils/EGLHelper.java | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java 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..2633ad681b --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java @@ -0,0 +1,295 @@ +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.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 + * + * @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: Renderer
+ * Index 2: Version
+ * Index 3: Extensions
+ * + * @return information retrieved through EGL. + */ + public String[] getEGLInfo() + { + String[] info = { + mGL.glGetString(GL10.GL_VENDOR), + mGL.glGetString(GL10.GL_RENDERER), + mGL.glGetString(GL10.GL_VERSION), + 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() + { + // Attributes for a visual in RGBA format with at least 8 bits per color. + int[] attribs = { + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_NONE + }; + + // Get total number of configs available. + int[] numConfigs = new int[1]; + if (!mEGL.eglChooseConfig(mDisplay, attribs, 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.eglChooseConfig(mDisplay, attribs, 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_RENDERABLE_TYPE, renderableType, + 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: + attribs[5] = EGL_OPENGL_ES_BIT; + ctx_attribs[1] = 1; + break; + + case EGL_OPENGL_BIT: + attribs[5] = EGL_OPENGL_BIT; + ctx_attribs[0] = EGL10.EGL_NONE; + break; + + case EGL_OPENGL_ES3_BIT_KHR: + attribs[5] = EGL_OPENGL_ES3_BIT_KHR; + ctx_attribs[1] = 3; + break; + + case EGL_OPENGL_ES2_BIT: + default: // Fall-back to GLES 2. + attribs[5] = EGL_OPENGL_ES2_BIT; + 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(); + } +} From 0dc437e94dc8cdcbec42e3c2a50427effdccdfda Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 21 Jan 2014 00:12:40 -0500 Subject: [PATCH 3/9] [Android] Finally check if regular OpenGL is possible on devices and display/hide it's fragment based upon this in AboutActivity.java. Also added another constructor to EGLHelper which can be used to quickly query for information. --- .../dolphinemu/about/AboutActivity.java | 65 ++++++++++++------- .../dolphinemu/utils/EGLHelper.java | 21 +++++- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index c3f0f61af8..70b15b9685 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -1,7 +1,7 @@ package org.dolphinemu.dolphinemu.about; import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment; +import org.dolphinemu.dolphinemu.utils.EGLHelper; import android.app.ActionBar; import android.app.ActionBar.Tab; @@ -21,7 +21,7 @@ import android.support.v4.view.ViewPager; public final class AboutActivity extends Activity implements TabListener { private ViewPager viewPager; - private boolean supportsGles3; + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); @Override protected void onCreate(Bundle savedInstanceState) @@ -32,9 +32,6 @@ public final class AboutActivity extends Activity implements TabListener setContentView(R.layout.viewpager); viewPager = (ViewPager) findViewById(R.id.pager); - // Check if GLES3 is supported - supportsGles3 = VideoSettingsFragment.SupportsGLES3(); - // Initialize the ViewPager adapter. final ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager()); viewPager.setAdapter(adapter); @@ -45,10 +42,10 @@ public final class AboutActivity extends Activity implements TabListener actionBar.addTab(actionBar.newTab().setText(R.string.general).setTabListener(this)); actionBar.addTab(actionBar.newTab().setText(R.string.cpu).setTabListener(this)); actionBar.addTab(actionBar.newTab().setText(R.string.gles_two).setTabListener(this)); - if (supportsGles3) + if (eglHelper.supportsGLES3()) actionBar.addTab(actionBar.newTab().setText(R.string.gles_three).setTabListener(this)); - // TODO: Check if Desktop GL is possible before enabling. - actionBar.addTab(actionBar.newTab().setText(R.string.desktop_gl).setTabListener(this)); + if (eglHelper.supportsOpenGL()) + actionBar.addTab(actionBar.newTab().setText(R.string.desktop_gl).setTabListener(this)); // Set the page change listener viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() @@ -61,6 +58,14 @@ public final class AboutActivity extends Activity implements TabListener }); } + @Override + public void onDestroy() + { + super.onDestroy(); + + eglHelper.closeHelper(); + } + @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { @@ -94,30 +99,46 @@ public final class AboutActivity extends Activity implements TabListener @Override public Fragment getItem(int position) { - switch (position) + if (position == 0) { - case 0: return new DolphinInfoFragment(); - // TODO: The rest of these fragments - case 1: return new Fragment(); // CPU - case 2: return new Fragment(); // GLES 2 - case 3: return new Fragment(); // GLES 3 - case 4: return new Fragment(); // Desktop GL - - default: // Should never happen - return null; + return new DolphinInfoFragment(); } + else if (position == 1) + { + return new Fragment(); // CPU + } + else if (position == 2) // GLES 2 + { + return new Fragment(); + } + else if (position == 3) // GLES 3 or OpenGL (depending on circumstances) + { + if (eglHelper.supportsGLES3()) + return new Fragment(); // TODO: Return the GLES 3 fragment in this case (normal case) + else + return new Fragment(); // TODO: Return the OpenGL fragment in this case (GLES3 not supported case) + } + else if (position == 4) // OpenGL fragment + { + return new Fragment(); + } + + // This should never happen. + return null; } @Override public int getCount() { - // TODO: In the future, make sure to take into account - // whether or not regular Desktop GL is possible. - if (supportsGles3) + if (eglHelper.supportsGLES3() && eglHelper.supportsOpenGL()) { return 5; } - else + else if (!eglHelper.supportsGLES3() && !eglHelper.supportsOpenGL()) + { + return 3; + } + else // Either regular OpenGL or GLES3 isn't supported { return 4; } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java index 2633ad681b..2f38f10a8a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java @@ -34,6 +34,21 @@ public final class EGLHelper 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 * @@ -85,8 +100,8 @@ public final class EGLHelper * Gets information through EGL.
*

* Index 0: Vendor
- * Index 1: Renderer
- * Index 2: Version
+ * Index 1: Version
+ * Index 2: Renderer
* Index 3: Extensions
* * @return information retrieved through EGL. @@ -95,8 +110,8 @@ public final class EGLHelper { String[] info = { mGL.glGetString(GL10.GL_VENDOR), - mGL.glGetString(GL10.GL_RENDERER), mGL.glGetString(GL10.GL_VERSION), + mGL.glGetString(GL10.GL_RENDERER), mGL.glGetString(GL10.GL_EXTENSIONS), }; From d3ccf1c7b56cf560298eead942f27cf675aff37e Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 21 Jan 2014 17:45:39 -0600 Subject: [PATCH 4/9] [android-about-menu-info] Have information populate the GLES2 and GLES3 tabs. There is a /lot/ of information in these tabs, we may have to think about changing how the information looks OpenGL isn't done yet since there are a million limits on desktop GL, may just show a few things and extensions there. --- .../dolphinemu/about/AboutActivity.java | 83 ++++++++++- .../dolphinemu/about/GLES2InfoFragment.java | 105 +++++++++++++ .../dolphinemu/about/GLES3InfoFragment.java | 139 ++++++++++++++++++ .../dolphinemu/utils/EGLHelper.java | 18 +++ 4 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index 70b15b9685..e852088c8b 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -10,9 +10,17 @@ import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; +import android.content.Context; import android.os.Bundle; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.util.List; /** * Activity for the about menu, which displays info @@ -23,6 +31,77 @@ public final class AboutActivity extends Activity implements TabListener private ViewPager viewPager; private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + // Represents an item in the multiple About fragments. + public static final class AboutFragmentItem + { + private final String title; + private final String subtitle; + + public AboutFragmentItem(String title, String subtitle) + { + this.title = title; + this.subtitle = subtitle; + } + + public String getTitle() + { + return title; + } + + public String getSubTitle() + { + return subtitle; + } + } + + // The adapter that manages the displaying of items in multiple About fragments. + public static final class InfoFragmentAdapter extends ArrayAdapter + { + private final Context ctx; + private final int id; + private final List items; + + public InfoFragmentAdapter(Context ctx, int id, List items) + { + super(ctx, id, items); + + this.ctx = ctx; + this.id = id; + this.items = items; + } + + @Override + public AboutFragmentItem getItem(int index) + { + return items.get(index); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) + { + if (convertView == null) + { + LayoutInflater vi = LayoutInflater.from(ctx); + convertView = vi.inflate(id, parent, false); + } + + final AboutFragmentItem item = items.get(position); + if (item != null) + { + TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); + + if (title != null) + title.setText(item.getTitle()); + + if (subtitle != null) + subtitle.setText(item.getSubTitle()); + } + + return convertView; + } + } + @Override protected void onCreate(Bundle savedInstanceState) { @@ -109,12 +188,12 @@ public final class AboutActivity extends Activity implements TabListener } else if (position == 2) // GLES 2 { - return new Fragment(); + return new GLES2InfoFragment(); } else if (position == 3) // GLES 3 or OpenGL (depending on circumstances) { if (eglHelper.supportsGLES3()) - return new Fragment(); // TODO: Return the GLES 3 fragment in this case (normal case) + return new GLES3InfoFragment(); // TODO: Return the GLES 3 fragment in this case (normal case) else return new Fragment(); // TODO: Return the OpenGL fragment in this case (GLES3 not supported case) } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java new file mode 100644 index 0000000000..befb098ff2 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java @@ -0,0 +1,105 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2 + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.about; + +import android.app.ListFragment; +import android.opengl.GLES10; +import android.opengl.GLES20; +import android.opengl.GLES30; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.utils.EGLHelper; + +import java.util.ArrayList; +import java.util.List; + +import javax.microedition.khronos.opengles.GL10; + +public class GLES2InfoFragment extends ListFragment { + + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + + public static final int TYPE_STRING = 0; + public static final int TYPE_INTEGER = 1; + public static final int TYPE_INTEGER_RANGE = 2; + + class Limit + { + public final String name; + public final int glEnum; + public final int type; + + public Limit(String name, int glEnum, int type) + { + this.name = name; + this.glEnum = glEnum; + this.type = type; + } + public String GetValue() + { + if (type == TYPE_INTEGER) + return Integer.toString(eglHelper.glGetInteger(glEnum)); + return eglHelper.glGetString(glEnum); + } + } + + private final Limit Limits[] = { + new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), + new Limit("Version", GL10.GL_VERSION, TYPE_STRING), + new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), + new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), + // GLES 2.0 Limits + //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, TYPE_INTEGER_RANGE), + //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, TYPE_INTEGER_RANGE), + new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, TYPE_INTEGER), + //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, TYPE_INTEGER_RANGE), + new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, TYPE_INTEGER), + new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, TYPE_INTEGER), + new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, TYPE_INTEGER), + new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, TYPE_INTEGER), + new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, TYPE_INTEGER), + new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, TYPE_INTEGER), + new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, TYPE_INTEGER), + new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, TYPE_INTEGER), + }; + + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + + + List Input = new ArrayList(); + + for(Limit limit : Limits) + { + Log.w("Dolphinemu", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); + } + + // Get extensions manually + String ExtensionsString = eglHelper.glGetString(GLES20.GL_EXTENSIONS); + String Extensions[] = ExtensionsString.split(" "); + String FinalExtensions = ""; + for (String Extension : Extensions) + FinalExtensions += Extension + "\n"; + Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 2.0 Extensions", FinalExtensions)); + + 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/GLES3InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java new file mode 100644 index 0000000000..1c34b83328 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java @@ -0,0 +1,139 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2 + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.about; + +import android.app.ListFragment; +import android.opengl.GLES10; +import android.opengl.GLES20; +import android.opengl.GLES30; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.utils.EGLHelper; + +import java.sql.Struct; +import java.util.ArrayList; +import java.util.List; + +import javax.microedition.khronos.opengles.GL10; + +public class GLES3InfoFragment extends ListFragment { + + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR); + + public static final int TYPE_STRING = 0; + public static final int TYPE_INTEGER = 1; + public static final int TYPE_INTEGER_RANGE = 2; + + class Limit + { + public final String name; + public final int glEnum; + public final int type; + + public Limit(String name, int glEnum, int type) + { + this.name = name; + this.glEnum = glEnum; + this.type = type; + } + public String GetValue() + { + if (type == TYPE_INTEGER) + return Integer.toString(eglHelper.glGetInteger(glEnum)); + return eglHelper.glGetString(glEnum); + } + } + + private final Limit Limits[] = { + new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), + new Limit("Version", GL10.GL_VERSION, TYPE_STRING), + new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), + new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), + // GLES 2.0 Limits + //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, TYPE_INTEGER_RANGE), + //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, TYPE_INTEGER_RANGE), + new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, TYPE_INTEGER), + //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, TYPE_INTEGER_RANGE), + new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, TYPE_INTEGER), + new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, TYPE_INTEGER), + new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, TYPE_INTEGER), + new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, TYPE_INTEGER), + new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), + new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, TYPE_INTEGER), + new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, TYPE_INTEGER), + new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, TYPE_INTEGER), + new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, TYPE_INTEGER), + // GLES 3.0 limits + new Limit("Max 3D Texture size", GLES30.GL_MAX_3D_TEXTURE_SIZE, TYPE_INTEGER), + new Limit("Max Element Vertices", GLES30.GL_MAX_ELEMENTS_VERTICES, TYPE_INTEGER), + new Limit("Max Element Indices", GLES30.GL_MAX_ELEMENTS_INDICES, TYPE_INTEGER), + new Limit("Max Draw Buffers", GLES30.GL_MAX_DRAW_BUFFERS, TYPE_INTEGER), + new Limit("Max Fragment Uniform Components", GLES30.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, TYPE_INTEGER), + new Limit("Max Vertex Uniform Components", GLES30.GL_MAX_VERTEX_UNIFORM_COMPONENTS, TYPE_INTEGER), + new Limit("Number of Extensions", GLES30.GL_NUM_EXTENSIONS, TYPE_INTEGER), + new Limit("Max Array Texture Layers", GLES30.GL_MAX_ARRAY_TEXTURE_LAYERS, TYPE_INTEGER), + new Limit("Min Program Texel Offset", GLES30.GL_MIN_PROGRAM_TEXEL_OFFSET, TYPE_INTEGER), + new Limit("Max Program Texel Offset", GLES30.GL_MAX_PROGRAM_TEXEL_OFFSET, TYPE_INTEGER), + new Limit("Max Varying Components", GLES30.GL_MAX_VARYING_COMPONENTS, TYPE_INTEGER), + new Limit("Max TF Varying Length", GLES30.GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, TYPE_INTEGER), + new Limit("Max TF Separate Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, TYPE_INTEGER), + new Limit("Max TF Interleaved Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, TYPE_INTEGER), + new Limit("Max TF Separate Attributes", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, TYPE_INTEGER), + new Limit("Max Color Attachments", GLES30.GL_MAX_COLOR_ATTACHMENTS, TYPE_INTEGER), + new Limit("Max Samples", GLES30.GL_MAX_SAMPLES, TYPE_INTEGER), + new Limit("Max Vertex UBOs", GLES30.GL_MAX_VERTEX_UNIFORM_BLOCKS, TYPE_INTEGER), + new Limit("Max Fragment UBOs", GLES30.GL_MAX_FRAGMENT_UNIFORM_BLOCKS, TYPE_INTEGER), + new Limit("Max Combined UBOs", GLES30.GL_MAX_COMBINED_UNIFORM_BLOCKS, TYPE_INTEGER), + new Limit("Max Uniform Buffer Bindings", GLES30.GL_MAX_UNIFORM_BUFFER_BINDINGS, TYPE_INTEGER), + new Limit("Max UBO Size", GLES30.GL_MAX_UNIFORM_BLOCK_SIZE, TYPE_INTEGER), + new Limit("Max Combined Vertex Uniform Components", GLES30.GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, TYPE_INTEGER), + new Limit("Max Combined Fragment Uniform Components", GLES30.GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, TYPE_INTEGER), + new Limit("UBO Alignment", GLES30.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, TYPE_INTEGER), + new Limit("Max Vertex Output Components", GLES30.GL_MAX_VERTEX_OUTPUT_COMPONENTS, TYPE_INTEGER), + new Limit("Max Fragment Input Components", GLES30.GL_MAX_FRAGMENT_INPUT_COMPONENTS, TYPE_INTEGER), + new Limit("Max Server Wait Timeout", GLES30.GL_MAX_SERVER_WAIT_TIMEOUT, TYPE_INTEGER), + new Limit("Program Binary Formats", GLES30.GL_NUM_PROGRAM_BINARY_FORMATS, TYPE_INTEGER), + new Limit("Max Element Index", GLES30.GL_MAX_ELEMENT_INDEX, TYPE_INTEGER), + new Limit("Sample Counts", GLES30.GL_NUM_SAMPLE_COUNTS, TYPE_INTEGER), + + }; + + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + + + List Input = new ArrayList(); + + for(Limit limit : Limits) + { + Log.w("Dolphinemu", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); + } + + // Get extensions manually + int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS); + String ExtensionsString = ""; + for (int indx = 0; indx < numExtensions; ++indx) + ExtensionsString += eglHelper.glGetStringi(GLES10.GL_EXTENSIONS, indx) + "\n"; + Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 3.0 Extensions", ExtensionsString)); + + 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/utils/EGLHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java index 2f38f10a8a..702cd00140 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java @@ -7,6 +7,7 @@ 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; /** @@ -307,4 +308,21 @@ public final class EGLHelper mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext); mGL = (GL10) mEGLContext.getGL(); } + + public String glGetString(int glEnum) + { + return mGL.glGetString(glEnum); + } + + public String glGetStringi(int glEnum, int index) + { + return GLES30.glGetStringi(glEnum, index); + } + + public int glGetInteger(int glEnum) + { + int[] val = new int[1]; + mGL.glGetIntegerv(glEnum, val, 0); + return val[0]; + } } From 7e9b8d18a70b26cb4ddbaa195e85a84d25f5f0fa Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 21 Jan 2014 17:55:00 -0600 Subject: [PATCH 5/9] [android-about-menu-info] Add desktop OpenGL tab population. Since showing every single limit that desktop OGL supports is crazy, Let's just show the basic information, and extensions. --- .../dolphinemu/about/AboutActivity.java | 4 +- .../dolphinemu/about/GLInfoFragment.java | 88 +++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index e852088c8b..c365a8172a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -195,11 +195,11 @@ public final class AboutActivity extends Activity implements TabListener if (eglHelper.supportsGLES3()) return new GLES3InfoFragment(); // TODO: Return the GLES 3 fragment in this case (normal case) else - return new Fragment(); // TODO: Return the OpenGL fragment in this case (GLES3 not supported case) + return new GLInfoFragment(); // TODO: Return the OpenGL fragment in this case (GLES3 not supported case) } else if (position == 4) // OpenGL fragment { - return new Fragment(); + return new GLInfoFragment(); } // This should never happen. diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java new file mode 100644 index 0000000000..7e8f541a0a --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java @@ -0,0 +1,88 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2 + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.about; + +import android.app.ListFragment; +import android.opengl.GLES10; +import android.opengl.GLES20; +import android.opengl.GLES30; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.utils.EGLHelper; + +import java.util.ArrayList; +import java.util.List; + +import javax.microedition.khronos.opengles.GL10; + +public class GLInfoFragment extends ListFragment { + + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT); + + public static final int TYPE_STRING = 0; + public static final int TYPE_INTEGER = 1; + public static final int TYPE_INTEGER_RANGE = 2; + + class Limit + { + public final String name; + public final int glEnum; + public final int type; + + public Limit(String name, int glEnum, int type) + { + this.name = name; + this.glEnum = glEnum; + this.type = type; + } + public String GetValue() + { + if (type == TYPE_INTEGER) + return Integer.toString(eglHelper.glGetInteger(glEnum)); + return eglHelper.glGetString(glEnum); + } + } + + private final Limit Limits[] = { + new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), + new Limit("Version", GL10.GL_VERSION, TYPE_STRING), + new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), + new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), + }; + + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + + + List Input = new ArrayList(); + + for(Limit limit : Limits) + { + Log.w("Dolphinemu", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); + } + + // Get extensions manually + int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS); + String ExtensionsString = ""; + for (int indx = 0; indx < numExtensions; ++indx) + ExtensionsString += eglHelper.glGetStringi(GLES10.GL_EXTENSIONS, indx) + "\n"; + Input.add(new AboutActivity.AboutFragmentItem("OpenGL Extensions", ExtensionsString)); + + AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); + rootView.setAdapter(adapter); + + return rootView; + } +} From 5c4d087e8fa85e5b667396d1efca937f09d99b8b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 22 Jan 2014 00:41:23 -0500 Subject: [PATCH 6/9] [Android] Greatly clean up the previous commits. Now here is the long list of cleaned up things: - Spaces -> Tabs | Consistency - Javadoc everything that was added and not documented. - Remove duplicated code regarding the adapter that used to reside in DolphinInfoFragment.java. Now it resides in AboutActivity.java without a second duplication of it. - Properly retrieve all of the contexts in the EGL initialization in EGLHelper.java. - Remove the attribute EGL_RENDERABLE_TYPE from the pbuffersurface attributes in EGLHelper.java. With this present, the EGL context will always fail to reinitialize if destroyed and attempted to be recreated. - Break the inner class Limit within GLES2InfoFragment.java, GLES3InfoFragment.java, and GLInfoFragment.java into its own single class. Greatly reduces code duplication. - Introduce a Type enum into Limit.java (one of the wildly rare cases in Java where an enum is actually an OK solution). Removes duplicated constants from the Java files stated in the previous bullet note. - Add a copyright comment to the top of EGLHelper.java. Forgot to do this initially, my bad. - Add some missing override annotations to GLES2InfoFragment.java, GLES3InfoFragment.java, and GLInfoFragment.java. - Use StringBuilders in the previously mentioned three Java files. This is better than using a String in this instance, as the String object won't have to be recreated multiple times (ala concatenation). - Fix some constant accessors in the previously mentioned three Java files. - Added the 'final' modifier to the above three classes and to Limit.java. These classes serve a single purpose only, and are not intended to be inherited. --- .../dolphinemu/about/AboutActivity.java | 120 +++++------ .../dolphinemu/about/DolphinInfoFragment.java | 77 +------ .../dolphinemu/about/GLES2InfoFragment.java | 127 +++++------- .../dolphinemu/about/GLES3InfoFragment.java | 193 ++++++++---------- .../dolphinemu/about/GLInfoFragment.java | 92 ++++----- .../dolphinemu/dolphinemu/about/Limit.java | 56 +++++ .../dolphinemu/utils/EGLHelper.java | 90 +++++--- 7 files changed, 352 insertions(+), 403 deletions(-) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index c365a8172a..2ab2d2b9e7 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -31,76 +31,76 @@ public final class AboutActivity extends Activity implements TabListener private ViewPager viewPager; private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); - // Represents an item in the multiple About fragments. - public static final class AboutFragmentItem - { - private final String title; - private final String subtitle; + // Represents an item in the multiple About fragments. + public static final class AboutFragmentItem + { + private final String title; + private final String subtitle; - public AboutFragmentItem(String title, String subtitle) - { - this.title = title; - this.subtitle = subtitle; - } + public AboutFragmentItem(String title, String subtitle) + { + this.title = title; + this.subtitle = subtitle; + } - public String getTitle() - { - return title; - } + public String getTitle() + { + return title; + } - public String getSubTitle() - { - return subtitle; - } - } + public String getSubTitle() + { + return subtitle; + } + } - // The adapter that manages the displaying of items in multiple About fragments. - public static final class InfoFragmentAdapter extends ArrayAdapter - { - private final Context ctx; - private final int id; - private final List items; + // The adapter that manages the displaying of items in multiple About fragments. + public static final class InfoFragmentAdapter extends ArrayAdapter + { + private final Context ctx; + private final int id; + private final List items; - public InfoFragmentAdapter(Context ctx, int id, List items) - { - super(ctx, id, items); + public InfoFragmentAdapter(Context ctx, int id, List items) + { + super(ctx, id, items); - this.ctx = ctx; - this.id = id; - this.items = items; - } + this.ctx = ctx; + this.id = id; + this.items = items; + } - @Override - public AboutFragmentItem getItem(int index) - { - return items.get(index); - } + @Override + public AboutFragmentItem getItem(int index) + { + return items.get(index); + } - @Override - public View getView(int position, View convertView, ViewGroup parent) - { - if (convertView == null) - { - LayoutInflater vi = LayoutInflater.from(ctx); - convertView = vi.inflate(id, parent, false); - } + @Override + public View getView(int position, View convertView, ViewGroup parent) + { + if (convertView == null) + { + LayoutInflater vi = LayoutInflater.from(ctx); + convertView = vi.inflate(id, parent, false); + } - final AboutFragmentItem item = items.get(position); - if (item != null) - { - TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); - TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); + final AboutFragmentItem item = items.get(position); + if (item != null) + { + TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); - if (title != null) - title.setText(item.getTitle()); + if (title != null) + title.setText(item.getTitle()); - if (subtitle != null) - subtitle.setText(item.getSubTitle()); - } + if (subtitle != null) + subtitle.setText(item.getSubTitle()); + } - return convertView; - } - } + return convertView; + } + } @Override protected void onCreate(Bundle savedInstanceState) @@ -193,9 +193,9 @@ public final class AboutActivity extends Activity implements TabListener else if (position == 3) // GLES 3 or OpenGL (depending on circumstances) { if (eglHelper.supportsGLES3()) - return new GLES3InfoFragment(); // TODO: Return the GLES 3 fragment in this case (normal case) + return new GLES3InfoFragment(); else - return new GLInfoFragment(); // TODO: Return the OpenGL fragment in this case (GLES3 not supported case) + return new GLInfoFragment(); // GLES3 not supported, but OpenGL is. } else if (position == 4) // OpenGL fragment { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java index fccc20925f..6820ae9923 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java @@ -7,20 +7,18 @@ package org.dolphinemu.dolphinemu.about; import android.app.ListFragment; -import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.ListView; -import android.widget.TextView; - import java.util.ArrayList; import java.util.List; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.about.AboutActivity.AboutFragmentItem; +import org.dolphinemu.dolphinemu.about.AboutActivity.InfoFragmentAdapter; import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment; /** @@ -47,75 +45,4 @@ public final class DolphinInfoFragment extends ListFragment return rootView; } - - // Represents an item in the DolphinInfoFragment. - private static final class AboutFragmentItem - { - private final String title; - private final String subtitle; - - public AboutFragmentItem(String title, String subtitle) - { - this.title = title; - this.subtitle = subtitle; - } - - public String getTitle() - { - return title; - } - - public String getSubTitle() - { - return subtitle; - } - } - - // The adapter that manages the displaying of items in this DolphinInfoFragment. - private static final class InfoFragmentAdapter extends ArrayAdapter - { - private final Context ctx; - private final int id; - private final List items; - - public InfoFragmentAdapter(Context ctx, int id, List items) - { - super(ctx, id, items); - - this.ctx = ctx; - this.id = id; - this.items = items; - } - - @Override - public AboutFragmentItem getItem(int index) - { - return items.get(index); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) - { - if (convertView == null) - { - LayoutInflater vi = LayoutInflater.from(ctx); - convertView = vi.inflate(id, parent, false); - } - - final AboutFragmentItem item = items.get(position); - if (item != null) - { - TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); - TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); - - if (title != null) - title.setText(item.getTitle()); - - if (subtitle != null) - subtitle.setText(item.getSubTitle()); - } - - return convertView; - } - } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java index befb098ff2..10556e3faf 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java @@ -7,9 +7,7 @@ package org.dolphinemu.dolphinemu.about; import android.app.ListFragment; -import android.opengl.GLES10; import android.opengl.GLES20; -import android.opengl.GLES30; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -18,88 +16,67 @@ import android.view.ViewGroup; import android.widget.ListView; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.about.Limit.Type; import org.dolphinemu.dolphinemu.utils.EGLHelper; import java.util.ArrayList; import java.util.List; -import javax.microedition.khronos.opengles.GL10; +/** + * {@link ListFragment} responsible for displaying + * information relating to OpenGL ES 2. + */ +public final class GLES2InfoFragment extends ListFragment +{ + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); -public class GLES2InfoFragment extends ListFragment { + private final Limit[] Limits = { + new Limit("Vendor", GLES20.GL_VENDOR, Type.STRING), + new Limit("Version", GLES20.GL_VERSION, Type.STRING), + new Limit("Renderer", GLES20.GL_RENDERER, Type.STRING), + new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, Type.STRING), + // GLES 2.0 Limits + //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE), + //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE), + new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, Type.INTEGER), + //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE), + new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, Type.INTEGER), + new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, Type.INTEGER), + new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, Type.INTEGER), + new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, Type.INTEGER), + new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, Type.INTEGER), + new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, Type.INTEGER), + new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, Type.INTEGER), + new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, Type.INTEGER), + }; - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + List Input = new ArrayList(); - public static final int TYPE_STRING = 0; - public static final int TYPE_INTEGER = 1; - public static final int TYPE_INTEGER_RANGE = 2; + for (Limit limit : Limits) + { + Log.i("GLES2InfoFragment", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper))); + } - class Limit - { - public final String name; - public final int glEnum; - public final int type; + // Get extensions manually + String[] extensions = eglHelper.glGetString(GLES20.GL_EXTENSIONS).split(" "); + StringBuilder extensionsBuilder = new StringBuilder(); + for (String extension : extensions) + { + extensionsBuilder.append(extension).append('\n'); + } + Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 2.0 Extensions", extensionsBuilder.toString())); - public Limit(String name, int glEnum, int type) - { - this.name = name; - this.glEnum = glEnum; - this.type = type; - } - public String GetValue() - { - if (type == TYPE_INTEGER) - return Integer.toString(eglHelper.glGetInteger(glEnum)); - return eglHelper.glGetString(glEnum); - } - } + AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); + rootView.setAdapter(adapter); - private final Limit Limits[] = { - new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), - new Limit("Version", GL10.GL_VERSION, TYPE_STRING), - new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), - new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), - // GLES 2.0 Limits - //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, TYPE_INTEGER_RANGE), - //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, TYPE_INTEGER_RANGE), - new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, TYPE_INTEGER), - //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, TYPE_INTEGER_RANGE), - new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, TYPE_INTEGER), - new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, TYPE_INTEGER), - new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, TYPE_INTEGER), - new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, TYPE_INTEGER), - new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, TYPE_INTEGER), - new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, TYPE_INTEGER), - new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, TYPE_INTEGER), - new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, TYPE_INTEGER), - }; - - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); - - - List Input = new ArrayList(); - - for(Limit limit : Limits) - { - Log.w("Dolphinemu", "Getting enum " + limit.name); - Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); - } - - // Get extensions manually - String ExtensionsString = eglHelper.glGetString(GLES20.GL_EXTENSIONS); - String Extensions[] = ExtensionsString.split(" "); - String FinalExtensions = ""; - for (String Extension : Extensions) - FinalExtensions += Extension + "\n"; - Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 2.0 Extensions", FinalExtensions)); - - AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); - rootView.setAdapter(adapter); - - return rootView; - } + return rootView; + } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java index 1c34b83328..563e46e21c 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java @@ -7,8 +7,6 @@ package org.dolphinemu.dolphinemu.about; import android.app.ListFragment; -import android.opengl.GLES10; -import android.opengl.GLES20; import android.opengl.GLES30; import android.os.Bundle; import android.util.Log; @@ -17,123 +15,100 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ListView; -import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.about.Limit.Type; import org.dolphinemu.dolphinemu.utils.EGLHelper; -import java.sql.Struct; import java.util.ArrayList; import java.util.List; -import javax.microedition.khronos.opengles.GL10; +/** + * {@link ListFragment} responsible for displaying + * information relating to OpenGL ES 3. + */ +public final class GLES3InfoFragment extends ListFragment +{ + private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR); -public class GLES3InfoFragment extends ListFragment { + private final Limit[] Limits = { + new Limit("Vendor", GLES30.GL_VENDOR, Type.STRING), + new Limit("Version", GLES30.GL_VERSION, Type.STRING), + new Limit("Renderer", GLES30.GL_RENDERER, Type.STRING), + new Limit("GLSL version", GLES30.GL_SHADING_LANGUAGE_VERSION, Type.STRING), + // GLES 2.0 Limits + //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE), + //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE), + new Limit("Max Texture Size", GLES30.GL_MAX_TEXTURE_SIZE, Type.INTEGER), + //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE), + new Limit("Subpixel Bits", GLES30.GL_SUBPIXEL_BITS, Type.INTEGER), + new Limit("Max Vertex Attributes", GLES30.GL_MAX_VERTEX_ATTRIBS, Type.INTEGER), + new Limit("Max Vertex Uniform Vectors", GLES30.GL_MAX_VERTEX_UNIFORM_VECTORS, Type.INTEGER), + new Limit("Max Varying Vectors", GLES30.GL_MAX_VARYING_VECTORS, Type.INTEGER), + new Limit("Max Combined Texture Units", GLES30.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Vertex Texture Units", GLES30.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Texture Units", GLES30.GL_MAX_TEXTURE_IMAGE_UNITS, Type.INTEGER), + new Limit("Max Fragment Uniform Vectors", GLES30.GL_MAX_FRAGMENT_UNIFORM_VECTORS, Type.INTEGER), + new Limit("Max Cubemap Texture Size", GLES30.GL_MAX_CUBE_MAP_TEXTURE_SIZE, Type.INTEGER), + new Limit("Shader Binary Formats", GLES30.GL_NUM_SHADER_BINARY_FORMATS, Type.INTEGER), + new Limit("Max Framebuffer Size", GLES30.GL_MAX_RENDERBUFFER_SIZE, Type.INTEGER), + // GLES 3.0 limits + new Limit("Max 3D Texture size", GLES30.GL_MAX_3D_TEXTURE_SIZE, Type.INTEGER), + new Limit("Max Element Vertices", GLES30.GL_MAX_ELEMENTS_VERTICES, Type.INTEGER), + new Limit("Max Element Indices", GLES30.GL_MAX_ELEMENTS_INDICES, Type.INTEGER), + new Limit("Max Draw Buffers", GLES30.GL_MAX_DRAW_BUFFERS, Type.INTEGER), + new Limit("Max Fragment Uniform Components", GLES30.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, Type.INTEGER), + new Limit("Max Vertex Uniform Components", GLES30.GL_MAX_VERTEX_UNIFORM_COMPONENTS, Type.INTEGER), + new Limit("Number of Extensions", GLES30.GL_NUM_EXTENSIONS, Type.INTEGER), + new Limit("Max Array Texture Layers", GLES30.GL_MAX_ARRAY_TEXTURE_LAYERS, Type.INTEGER), + new Limit("Min Program Texel Offset", GLES30.GL_MIN_PROGRAM_TEXEL_OFFSET, Type.INTEGER), + new Limit("Max Program Texel Offset", GLES30.GL_MAX_PROGRAM_TEXEL_OFFSET, Type.INTEGER), + new Limit("Max Varying Components", GLES30.GL_MAX_VARYING_COMPONENTS, Type.INTEGER), + new Limit("Max TF Varying Length", GLES30.GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, Type.INTEGER), + new Limit("Max TF Separate Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, Type.INTEGER), + new Limit("Max TF Interleaved Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, Type.INTEGER), + new Limit("Max TF Separate Attributes", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, Type.INTEGER), + new Limit("Max Color Attachments", GLES30.GL_MAX_COLOR_ATTACHMENTS, Type.INTEGER), + new Limit("Max Samples", GLES30.GL_MAX_SAMPLES, Type.INTEGER), + new Limit("Max Vertex UBOs", GLES30.GL_MAX_VERTEX_UNIFORM_BLOCKS, Type.INTEGER), + new Limit("Max Fragment UBOs", GLES30.GL_MAX_FRAGMENT_UNIFORM_BLOCKS, Type.INTEGER), + new Limit("Max Combined UBOs", GLES30.GL_MAX_COMBINED_UNIFORM_BLOCKS, Type.INTEGER), + new Limit("Max Uniform Buffer Bindings", GLES30.GL_MAX_UNIFORM_BUFFER_BINDINGS, Type.INTEGER), + new Limit("Max UBO Size", GLES30.GL_MAX_UNIFORM_BLOCK_SIZE, Type.INTEGER), + new Limit("Max Combined Vertex Uniform Components", GLES30.GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, Type.INTEGER), + new Limit("Max Combined Fragment Uniform Components", GLES30.GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, Type.INTEGER), + new Limit("UBO Alignment", GLES30.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, Type.INTEGER), + new Limit("Max Vertex Output Components", GLES30.GL_MAX_VERTEX_OUTPUT_COMPONENTS, Type.INTEGER), + new Limit("Max Fragment Input Components", GLES30.GL_MAX_FRAGMENT_INPUT_COMPONENTS, Type.INTEGER), + new Limit("Max Server Wait Timeout", GLES30.GL_MAX_SERVER_WAIT_TIMEOUT, Type.INTEGER), + new Limit("Program Binary Formats", GLES30.GL_NUM_PROGRAM_BINARY_FORMATS, Type.INTEGER), + new Limit("Max Element Index", GLES30.GL_MAX_ELEMENT_INDEX, Type.INTEGER), + new Limit("Sample Counts", GLES30.GL_NUM_SAMPLE_COUNTS, Type.INTEGER), + }; - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR); + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + List Input = new ArrayList(); - public static final int TYPE_STRING = 0; - public static final int TYPE_INTEGER = 1; - public static final int TYPE_INTEGER_RANGE = 2; + for (Limit limit : Limits) + { + Log.i("GLES3InfoFragment", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper))); + } - class Limit - { - public final String name; - public final int glEnum; - public final int type; + // 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(GLES30.GL_EXTENSIONS, i)).append('\n'); + } + Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 3.0 Extensions", extensionsBuilder.toString())); - public Limit(String name, int glEnum, int type) - { - this.name = name; - this.glEnum = glEnum; - this.type = type; - } - public String GetValue() - { - if (type == TYPE_INTEGER) - return Integer.toString(eglHelper.glGetInteger(glEnum)); - return eglHelper.glGetString(glEnum); - } - } + AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); + rootView.setAdapter(adapter); - private final Limit Limits[] = { - new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), - new Limit("Version", GL10.GL_VERSION, TYPE_STRING), - new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), - new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), - // GLES 2.0 Limits - //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, TYPE_INTEGER_RANGE), - //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, TYPE_INTEGER_RANGE), - new Limit("Max Texture Size", GLES20.GL_MAX_TEXTURE_SIZE, TYPE_INTEGER), - //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, TYPE_INTEGER_RANGE), - new Limit("Subpixel Bits", GLES20.GL_SUBPIXEL_BITS, TYPE_INTEGER), - new Limit("Max Vertex Attributes", GLES20.GL_MAX_VERTEX_ATTRIBS, TYPE_INTEGER), - new Limit("Max Vertex Uniform Vectors", GLES20.GL_MAX_VERTEX_UNIFORM_VECTORS, TYPE_INTEGER), - new Limit("Max Varying Vectors", GLES20.GL_MAX_VARYING_VECTORS, TYPE_INTEGER), - new Limit("Max Combined Texture Units", GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Vertex Texture Units", GLES20.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Texture Units", GLES20.GL_MAX_TEXTURE_IMAGE_UNITS, TYPE_INTEGER), - new Limit("Max Fragment Uniform Vectors", GLES20.GL_MAX_FRAGMENT_UNIFORM_VECTORS, TYPE_INTEGER), - new Limit("Max Cubemap Texture Size", GLES20.GL_MAX_CUBE_MAP_TEXTURE_SIZE, TYPE_INTEGER), - new Limit("Shader Binary Formats", GLES20.GL_NUM_SHADER_BINARY_FORMATS, TYPE_INTEGER), - new Limit("Max Framebuffer Size", GLES20.GL_MAX_RENDERBUFFER_SIZE, TYPE_INTEGER), - // GLES 3.0 limits - new Limit("Max 3D Texture size", GLES30.GL_MAX_3D_TEXTURE_SIZE, TYPE_INTEGER), - new Limit("Max Element Vertices", GLES30.GL_MAX_ELEMENTS_VERTICES, TYPE_INTEGER), - new Limit("Max Element Indices", GLES30.GL_MAX_ELEMENTS_INDICES, TYPE_INTEGER), - new Limit("Max Draw Buffers", GLES30.GL_MAX_DRAW_BUFFERS, TYPE_INTEGER), - new Limit("Max Fragment Uniform Components", GLES30.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, TYPE_INTEGER), - new Limit("Max Vertex Uniform Components", GLES30.GL_MAX_VERTEX_UNIFORM_COMPONENTS, TYPE_INTEGER), - new Limit("Number of Extensions", GLES30.GL_NUM_EXTENSIONS, TYPE_INTEGER), - new Limit("Max Array Texture Layers", GLES30.GL_MAX_ARRAY_TEXTURE_LAYERS, TYPE_INTEGER), - new Limit("Min Program Texel Offset", GLES30.GL_MIN_PROGRAM_TEXEL_OFFSET, TYPE_INTEGER), - new Limit("Max Program Texel Offset", GLES30.GL_MAX_PROGRAM_TEXEL_OFFSET, TYPE_INTEGER), - new Limit("Max Varying Components", GLES30.GL_MAX_VARYING_COMPONENTS, TYPE_INTEGER), - new Limit("Max TF Varying Length", GLES30.GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, TYPE_INTEGER), - new Limit("Max TF Separate Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, TYPE_INTEGER), - new Limit("Max TF Interleaved Components", GLES30.GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, TYPE_INTEGER), - new Limit("Max TF Separate Attributes", GLES30.GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, TYPE_INTEGER), - new Limit("Max Color Attachments", GLES30.GL_MAX_COLOR_ATTACHMENTS, TYPE_INTEGER), - new Limit("Max Samples", GLES30.GL_MAX_SAMPLES, TYPE_INTEGER), - new Limit("Max Vertex UBOs", GLES30.GL_MAX_VERTEX_UNIFORM_BLOCKS, TYPE_INTEGER), - new Limit("Max Fragment UBOs", GLES30.GL_MAX_FRAGMENT_UNIFORM_BLOCKS, TYPE_INTEGER), - new Limit("Max Combined UBOs", GLES30.GL_MAX_COMBINED_UNIFORM_BLOCKS, TYPE_INTEGER), - new Limit("Max Uniform Buffer Bindings", GLES30.GL_MAX_UNIFORM_BUFFER_BINDINGS, TYPE_INTEGER), - new Limit("Max UBO Size", GLES30.GL_MAX_UNIFORM_BLOCK_SIZE, TYPE_INTEGER), - new Limit("Max Combined Vertex Uniform Components", GLES30.GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, TYPE_INTEGER), - new Limit("Max Combined Fragment Uniform Components", GLES30.GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, TYPE_INTEGER), - new Limit("UBO Alignment", GLES30.GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, TYPE_INTEGER), - new Limit("Max Vertex Output Components", GLES30.GL_MAX_VERTEX_OUTPUT_COMPONENTS, TYPE_INTEGER), - new Limit("Max Fragment Input Components", GLES30.GL_MAX_FRAGMENT_INPUT_COMPONENTS, TYPE_INTEGER), - new Limit("Max Server Wait Timeout", GLES30.GL_MAX_SERVER_WAIT_TIMEOUT, TYPE_INTEGER), - new Limit("Program Binary Formats", GLES30.GL_NUM_PROGRAM_BINARY_FORMATS, TYPE_INTEGER), - new Limit("Max Element Index", GLES30.GL_MAX_ELEMENT_INDEX, TYPE_INTEGER), - new Limit("Sample Counts", GLES30.GL_NUM_SAMPLE_COUNTS, TYPE_INTEGER), - - }; - - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); - - - List Input = new ArrayList(); - - for(Limit limit : Limits) - { - Log.w("Dolphinemu", "Getting enum " + limit.name); - Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); - } - - // Get extensions manually - int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS); - String ExtensionsString = ""; - for (int indx = 0; indx < numExtensions; ++indx) - ExtensionsString += eglHelper.glGetStringi(GLES10.GL_EXTENSIONS, indx) + "\n"; - Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 3.0 Extensions", ExtensionsString)); - - AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); - rootView.setAdapter(adapter); - - return rootView; - } + return rootView; + } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java index 7e8f541a0a..14afce2028 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java @@ -7,7 +7,6 @@ package org.dolphinemu.dolphinemu.about; import android.app.ListFragment; -import android.opengl.GLES10; import android.opengl.GLES20; import android.opengl.GLES30; import android.os.Bundle; @@ -18,6 +17,7 @@ import android.view.ViewGroup; import android.widget.ListView; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.about.Limit.Type; import org.dolphinemu.dolphinemu.utils.EGLHelper; import java.util.ArrayList; @@ -25,64 +25,46 @@ import java.util.List; import javax.microedition.khronos.opengles.GL10; -public class GLInfoFragment extends ListFragment { +/** + * {@link ListFragment} responsible for displaying + * information relating to OpenGL. + */ +public final class GLInfoFragment extends ListFragment +{ + private EGLHelper eglHelper; - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT); + private final Limit[] Limits = { + new Limit("Vendor", GL10.GL_VENDOR, Type.STRING), + new Limit("Version", GL10.GL_VERSION, Type.STRING), + new Limit("Renderer", GL10.GL_RENDERER, Type.STRING), + new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, Type.STRING), + }; - public static final int TYPE_STRING = 0; - public static final int TYPE_INTEGER = 1; - public static final int TYPE_INTEGER_RANGE = 2; + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + List Input = new ArrayList(); - class Limit - { - public final String name; - public final int glEnum; - public final int type; + for (Limit limit : Limits) + { + Log.i("GLInfoFragment", "Getting enum " + limit.name); + Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper))); + } - public Limit(String name, int glEnum, int type) - { - this.name = name; - this.glEnum = glEnum; - this.type = type; - } - public String GetValue() - { - if (type == TYPE_INTEGER) - return Integer.toString(eglHelper.glGetInteger(glEnum)); - return eglHelper.glGetString(glEnum); - } - } + // 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())); - private final Limit Limits[] = { - new Limit("Vendor", GL10.GL_VENDOR, TYPE_STRING), - new Limit("Version", GL10.GL_VERSION, TYPE_STRING), - new Limit("Renderer", GL10.GL_RENDERER, TYPE_STRING), - new Limit("GLSL version", GLES20.GL_SHADING_LANGUAGE_VERSION, TYPE_STRING), - }; + AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); + rootView.setAdapter(adapter); - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); - - - List Input = new ArrayList(); - - for(Limit limit : Limits) - { - Log.w("Dolphinemu", "Getting enum " + limit.name); - Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue())); - } - - // Get extensions manually - int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS); - String ExtensionsString = ""; - for (int indx = 0; indx < numExtensions; ++indx) - ExtensionsString += eglHelper.glGetStringi(GLES10.GL_EXTENSIONS, indx) + "\n"; - Input.add(new AboutActivity.AboutFragmentItem("OpenGL Extensions", ExtensionsString)); - - AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); - rootView.setAdapter(adapter); - - return rootView; - } + 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..70b1be5b06 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java @@ -0,0 +1,56 @@ +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)); + + + return context.glGetString(glEnum); + } +} \ No newline at end of file diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java index 702cd00140..94ea903ae6 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/EGLHelper.java @@ -1,3 +1,9 @@ +/** + * 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; @@ -216,17 +222,9 @@ public final class EGLHelper // Detects the specific kind of GL modes that are supported private boolean detect() { - // Attributes for a visual in RGBA format with at least 8 bits per color. - int[] attribs = { - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_NONE - }; - // Get total number of configs available. int[] numConfigs = new int[1]; - if (!mEGL.eglChooseConfig(mDisplay, attribs, null, 0, numConfigs)) + if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs)) { Log.e("EGLHelper", "Error retrieving number of EGL configs available."); return false; @@ -234,7 +232,7 @@ public final class EGLHelper // Now get all the configurations mEGLConfigs = new EGLConfig[numConfigs[0]]; - if (!mEGL.eglChooseConfig(mDisplay, attribs, mEGLConfigs, mEGLConfigs.length, numConfigs)) + if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs)) { Log.e("EGLHelper", "Error retrieving all EGL configs."); return false; @@ -266,7 +264,6 @@ public final class EGLHelper int[] attribs = { EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, - EGL10.EGL_RENDERABLE_TYPE, renderableType, EGL10.EGL_NONE }; @@ -282,23 +279,19 @@ public final class EGLHelper switch (renderableType) { case EGL_OPENGL_ES_BIT: - attribs[5] = EGL_OPENGL_ES_BIT; ctx_attribs[1] = 1; break; case EGL_OPENGL_BIT: - attribs[5] = EGL_OPENGL_BIT; ctx_attribs[0] = EGL10.EGL_NONE; break; case EGL_OPENGL_ES3_BIT_KHR: - attribs[5] = EGL_OPENGL_ES3_BIT_KHR; ctx_attribs[1] = 3; break; case EGL_OPENGL_ES2_BIT: default: // Fall-back to GLES 2. - attribs[5] = EGL_OPENGL_ES2_BIT; ctx_attribs[1] = 2; break; } @@ -309,20 +302,59 @@ public final class EGLHelper mGL = (GL10) mEGLContext.getGL(); } - public String glGetString(int glEnum) - { - return mGL.glGetString(glEnum); - } + /** + * 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); + } - public String glGetStringi(int glEnum, int index) - { - return GLES30.glGetStringi(glEnum, index); - } + /** + * 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); + } - public int glGetInteger(int glEnum) - { - int[] val = new int[1]; - mGL.glGetIntegerv(glEnum, val, 0); - return val[0]; - } + /** + * 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]; + } } From 36863bf7b8ecf6c33bbe412b48a3af280d907d04 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 22 Jan 2014 11:56:25 -0500 Subject: [PATCH 7/9] [Android] Get rid of the version check class in VideoSettingsFragment.java. Not needed anymore since the introduction of the EGLHelper class. Also decouples some classes from the VideoSettingsFragment.java class (yay). - Minor other change is that the EGL helper fields in GLES3InfoFragment.java, GLES2InfoFragment.java, and GLInfoFragment.java are made final. --- .../dolphinemu/about/AboutActivity.java | 2 +- .../dolphinemu/about/DolphinInfoFragment.java | 6 +- .../dolphinemu/about/GLES2InfoFragment.java | 2 +- .../dolphinemu/about/GLES3InfoFragment.java | 2 +- .../dolphinemu/about/GLInfoFragment.java | 3 +- .../emulation/EmulationActivity.java | 45 +++- .../settings/video/VideoSettingsFragment.java | 203 +++--------------- 7 files changed, 76 insertions(+), 187 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index 2ab2d2b9e7..ab2bda3e0a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -29,7 +29,7 @@ import java.util.List; public final class AboutActivity extends Activity implements TabListener { private ViewPager viewPager; - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); // Represents an item in the multiple About fragments. public static final class AboutFragmentItem diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java index 6820ae9923..af7d1a14e2 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/DolphinInfoFragment.java @@ -12,6 +12,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; + import java.util.ArrayList; import java.util.List; @@ -19,7 +20,7 @@ import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.about.AboutActivity.AboutFragmentItem; import org.dolphinemu.dolphinemu.about.AboutActivity.InfoFragmentAdapter; -import org.dolphinemu.dolphinemu.settings.video.VideoSettingsFragment; +import org.dolphinemu.dolphinemu.utils.EGLHelper; /** * Represents the about screen. @@ -30,13 +31,14 @@ public final class DolphinInfoFragment extends ListFragment public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); final String yes = getString(R.string.yes); final String no = getString(R.string.no); List Input = new ArrayList(); Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString())); - Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); + Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), eglHelper.supportsGLES3() ? yes : no)); Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); InfoFragmentAdapter adapter = new InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java index 10556e3faf..12d5374d79 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES2InfoFragment.java @@ -28,7 +28,7 @@ import java.util.List; */ public final class GLES2InfoFragment extends ListFragment { - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); private final Limit[] Limits = { new Limit("Vendor", GLES20.GL_VENDOR, Type.STRING), diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java index 563e46e21c..3bf6e8a3cd 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java @@ -28,7 +28,7 @@ import java.util.List; */ public final class GLES3InfoFragment extends ListFragment { - private EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR); + private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR); private final Limit[] Limits = { new Limit("Vendor", GLES30.GL_VENDOR, Type.STRING), diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java index 14afce2028..a3d7167528 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLInfoFragment.java @@ -31,7 +31,7 @@ import javax.microedition.khronos.opengles.GL10; */ public final class GLInfoFragment extends ListFragment { - private EGLHelper eglHelper; + private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT); private final Limit[] Limits = { new Limit("Vendor", GL10.GL_VENDOR, Type.STRING), @@ -43,7 +43,6 @@ public final class GLInfoFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_BIT); ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); List Input = new ArrayList(); 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/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()); + } } From 521aa631dcc6328a7ac31e51c457ff7115096358 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 22 Jan 2014 12:28:46 -0500 Subject: [PATCH 8/9] [Android] Parse integer ranges in the GLES3 info tab. The info we retrieve will only ever have 2 elements given back to us. --- .../dolphinemu/dolphinemu/about/GLES3InfoFragment.java | 6 +++--- .../src/org/dolphinemu/dolphinemu/about/Limit.java | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java index 3bf6e8a3cd..797a047b14 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/GLES3InfoFragment.java @@ -36,10 +36,10 @@ public final class GLES3InfoFragment extends ListFragment new Limit("Renderer", GLES30.GL_RENDERER, Type.STRING), new Limit("GLSL version", GLES30.GL_SHADING_LANGUAGE_VERSION, Type.STRING), // GLES 2.0 Limits - //new Limit("Aliased Point Size", GLES20.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE), - //new Limit("Aliased Line Width ", GLES20.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE), + new Limit("Aliased Point Size", GLES30.GL_ALIASED_POINT_SIZE_RANGE, Type.INTEGER_RANGE), + new Limit("Aliased Line Width ", GLES30.GL_ALIASED_LINE_WIDTH_RANGE, Type.INTEGER_RANGE), new Limit("Max Texture Size", GLES30.GL_MAX_TEXTURE_SIZE, Type.INTEGER), - //new Limit("Viewport Dimensions", GLES20.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE), + new Limit("Viewport Dimensions", GLES30.GL_MAX_VIEWPORT_DIMS, Type.INTEGER_RANGE), new Limit("Subpixel Bits", GLES30.GL_SUBPIXEL_BITS, Type.INTEGER), new Limit("Max Vertex Attributes", GLES30.GL_MAX_VERTEX_ATTRIBS, Type.INTEGER), new Limit("Max Vertex Uniform Vectors", GLES30.GL_MAX_VERTEX_UNIFORM_VECTORS, Type.INTEGER), diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java index 70b1be5b06..96b206b837 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/Limit.java @@ -48,9 +48,18 @@ final class 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 From b9e7749fe697d878bba74898a971c38948cb2aaf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 26 Jan 2014 21:37:43 -0500 Subject: [PATCH 9/9] [Android] Implement CPU info retrieval within the about menu. ARM only at the moment. Could potentially support x86 and MIPS if necessary. Capable of parsing the manufacturer codes and part IDs of some (but not all part numbers). If anyone knows of part numbers that aren't in the list, please report them. --- Source/Android/res/values-ja/strings.xml | 11 + Source/Android/res/values/strings.xml | 11 + .../dolphinemu/about/AboutActivity.java | 6 +- .../dolphinemu/about/CPUInfoFragment.java | 47 ++ .../dolphinemu/utils/CPUHelper.java | 400 ++++++++++++++++++ 5 files changed, 471 insertions(+), 4 deletions(-) create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index 9d2dfe37eb..cb206ae8a2 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -17,6 +17,17 @@ GLES 3 OpenGL + + CPU ABI 1 + CPU ABI 2 + CPU情報 + CPUタイプ + CPUの命令セットと機能 + CPUコア + CPUの実装 + ハードウェア + 不明 (%1$d)。 我々はそれを文書化することができますので、この番号を報告してください。 + 現在のディレクトリ: %1$s 親ディレクトリ diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index b60a56e73c..0fae5bab6c 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -18,6 +18,17 @@ GLES 3 OpenGL + + CPU ABI 1 + CPU ABI 2 + CPU Info + CPU Type + CPU Features + Number of Cores + CPU Implementer + Hardware + Unknown (%1$d). Please report this number so it can be documented! + Current Dir: %1$s Parent Directory diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index ab2bda3e0a..d544d7e6c2 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -57,7 +57,6 @@ public final class AboutActivity extends Activity implements TabListener // The adapter that manages the displaying of items in multiple About fragments. public static final class InfoFragmentAdapter extends ArrayAdapter { - private final Context ctx; private final int id; private final List items; @@ -65,7 +64,6 @@ public final class AboutActivity extends Activity implements TabListener { super(ctx, id, items); - this.ctx = ctx; this.id = id; this.items = items; } @@ -81,7 +79,7 @@ public final class AboutActivity extends Activity implements TabListener { if (convertView == null) { - LayoutInflater vi = LayoutInflater.from(ctx); + LayoutInflater vi = LayoutInflater.from(getContext()); convertView = vi.inflate(id, parent, false); } @@ -184,7 +182,7 @@ public final class AboutActivity extends Activity implements TabListener } else if (position == 1) { - return new Fragment(); // CPU + return new CPUInfoFragment(); // CPU } else if (position == 2) // GLES 2 { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java new file mode 100644 index 0000000000..ddf1e0f816 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java @@ -0,0 +1,47 @@ +package org.dolphinemu.dolphinemu.about; + +import java.util.ArrayList; +import java.util.List; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.about.AboutActivity.AboutFragmentItem; +import org.dolphinemu.dolphinemu.utils.CPUHelper; + +import android.app.ListFragment; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +/** + * {@link ListFragment class that is responsible + * for displaying information related to the CPU. + */ +public final class CPUInfoFragment extends ListFragment +{ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + List items = new ArrayList(); + + CPUHelper cpuHelper = new CPUHelper(getActivity()); + + items.add(new AboutFragmentItem(getString(R.string.cpu_info), cpuHelper.getProcessorInfo())); + items.add(new AboutFragmentItem(getString(R.string.cpu_type), cpuHelper.getProcessorType())); + items.add(new AboutFragmentItem(getString(R.string.cpu_abi_one), Build.CPU_ABI)); + items.add(new AboutFragmentItem(getString(R.string.cpu_abi_two), Build.CPU_ABI2)); + items.add(new AboutFragmentItem(getString(R.string.num_cores), Integer.toString(cpuHelper.getNumCores()))); + items.add(new AboutFragmentItem(getString(R.string.cpu_features), cpuHelper.getFeatures())); + items.add(new AboutFragmentItem(getString(R.string.cpu_hardware), Build.HARDWARE)); + if (CPUHelper.isARM()) + items.add(new AboutFragmentItem(getString(R.string.cpu_implementer), cpuHelper.getImplementer())); + + AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, items); + rootView.setAdapter(adapter); + + return rootView; + } +} 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); + } + } +}