Merge pull request #4 from lioncash/android-about-menu-info
Expand the Android app's about menu to include additional info about a user's device.
This commit is contained in:
commit
7b459d2463
|
@ -33,6 +33,7 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="org.dolphinemu.dolphinemu.about.AboutActivity"/>
|
||||
<activity android:name="org.dolphinemu.dolphinemu.gamelist.GameListActivity"/>
|
||||
|
||||
<activity
|
||||
|
|
|
@ -12,6 +12,21 @@
|
|||
<string name="build_revision">ビルドのバージョン</string>
|
||||
<string name="supports_gles3">サポートのOpenGL ES 3</string>
|
||||
<string name="supports_neon">サポートのNEON</string>
|
||||
<string name="cpu">CPU</string>
|
||||
<string name="gles_two">GLES 2</string>
|
||||
<string name="gles_three">GLES 3</string>
|
||||
<string name="desktop_gl">OpenGL</string>
|
||||
|
||||
<!-- About Menu - CPU Info -->
|
||||
<string name="cpu_abi_one">CPU ABI 1</string>
|
||||
<string name="cpu_abi_two">CPU ABI 2</string>
|
||||
<string name="cpu_info">CPU情報</string>
|
||||
<string name="cpu_type">CPUタイプ</string>
|
||||
<string name="cpu_features">CPUの命令セットと機能</string>
|
||||
<string name="num_cores">CPUコア</string>
|
||||
<string name="cpu_implementer">CPUの実装</string>
|
||||
<string name="cpu_hardware">ハードウェア</string>
|
||||
<string name="unknown_part_num">不明 (%1$d)。 我々はそれを文書化することができますので、この番号を報告してください。 </string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">現在のディレクトリ: %1$s</string>
|
||||
|
|
|
@ -12,6 +12,22 @@
|
|||
<string name="build_revision">Build Revision</string>
|
||||
<string name="supports_gles3">Supports OpenGL ES 3</string>
|
||||
<string name="supports_neon">Supports NEON</string>
|
||||
<string name="general">General</string>
|
||||
<string name="cpu">CPU</string>
|
||||
<string name="gles_two">GLES 2</string>
|
||||
<string name="gles_three">GLES 3</string>
|
||||
<string name="desktop_gl">OpenGL</string>
|
||||
|
||||
<!-- About Menu - CPU Info -->
|
||||
<string name="cpu_abi_one">CPU ABI 1</string>
|
||||
<string name="cpu_abi_two">CPU ABI 2</string>
|
||||
<string name="cpu_info">CPU Info</string>
|
||||
<string name="cpu_type">CPU Type</string>
|
||||
<string name="cpu_features">CPU Features</string>
|
||||
<string name="num_cores">Number of Cores</string>
|
||||
<string name="cpu_implementer">CPU Implementer</string>
|
||||
<string name="cpu_hardware">Hardware</string>
|
||||
<string name="unknown_part_num">Unknown (%1$d). Please report this number so it can be documented!</string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">Current Dir: %1$s</string>
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
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.settings.video.VideoSettingsFragment;
|
||||
|
||||
/**
|
||||
* Represents the about screen.
|
||||
*/
|
||||
public final class AboutFragment extends ListFragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
|
||||
final String yes = getString(R.string.yes);
|
||||
final String no = getString(R.string.no);
|
||||
|
||||
List<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
|
||||
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_neon), NativeLibrary.SupportsNEON() ? yes : no));
|
||||
|
||||
AboutFragmentAdapter adapter = new AboutFragmentAdapter(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.
|
||||
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 AboutFragment.
|
||||
private static final class AboutFragmentAdapter extends ArrayAdapter<AboutFragmentItem>
|
||||
{
|
||||
private final Context ctx;
|
||||
private final int id;
|
||||
private final List<AboutFragmentItem> items;
|
||||
|
||||
public AboutFragmentAdapter(Context ctx, int id, List<AboutFragmentItem> 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
package org.dolphinemu.dolphinemu.about;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.utils.EGLHelper;
|
||||
|
||||
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.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
|
||||
* related to the CPU and GPU. Along with misc other info.
|
||||
*/
|
||||
public final class AboutActivity extends Activity implements TabListener
|
||||
{
|
||||
private ViewPager viewPager;
|
||||
private final 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<AboutFragmentItem>
|
||||
{
|
||||
private final int id;
|
||||
private final List<AboutFragmentItem> items;
|
||||
|
||||
public InfoFragmentAdapter(Context ctx, int id, List<AboutFragmentItem> items)
|
||||
{
|
||||
super(ctx, id, items);
|
||||
|
||||
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(getContext());
|
||||
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)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set the view pager
|
||||
setContentView(R.layout.viewpager);
|
||||
viewPager = (ViewPager) findViewById(R.id.pager);
|
||||
|
||||
// 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 (eglHelper.supportsGLES3())
|
||||
actionBar.addTab(actionBar.newTab().setText(R.string.gles_three).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()
|
||||
{
|
||||
@Override
|
||||
public void onPageSelected(int position)
|
||||
{
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
|
||||
eglHelper.closeHelper();
|
||||
}
|
||||
|
||||
@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)
|
||||
{
|
||||
if (position == 0)
|
||||
{
|
||||
return new DolphinInfoFragment();
|
||||
}
|
||||
else if (position == 1)
|
||||
{
|
||||
return new CPUInfoFragment(); // CPU
|
||||
}
|
||||
else if (position == 2) // GLES 2
|
||||
{
|
||||
return new GLES2InfoFragment();
|
||||
}
|
||||
else if (position == 3) // GLES 3 or OpenGL (depending on circumstances)
|
||||
{
|
||||
if (eglHelper.supportsGLES3())
|
||||
return new GLES3InfoFragment();
|
||||
else
|
||||
return new GLInfoFragment(); // GLES3 not supported, but OpenGL is.
|
||||
}
|
||||
else if (position == 4) // OpenGL fragment
|
||||
{
|
||||
return new GLInfoFragment();
|
||||
}
|
||||
|
||||
// This should never happen.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
if (eglHelper.supportsGLES3() && eglHelper.supportsOpenGL())
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else if (!eglHelper.supportsGLES3() && !eglHelper.supportsOpenGL())
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else // Either regular OpenGL or GLES3 isn't supported
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<AboutActivity.AboutFragmentItem> items = new ArrayList<AboutActivity.AboutFragmentItem>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
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.utils.EGLHelper;
|
||||
|
||||
/**
|
||||
* Represents the about screen.
|
||||
*/
|
||||
public final class DolphinInfoFragment extends ListFragment
|
||||
{
|
||||
@Override
|
||||
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<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
|
||||
Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString()));
|
||||
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);
|
||||
rootView.setAdapter(adapter);
|
||||
rootView.setEnabled(false); // Makes the list view non-clickable.
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 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.GLES20;
|
||||
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.about.Limit.Type;
|
||||
import org.dolphinemu.dolphinemu.utils.EGLHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link ListFragment} responsible for displaying
|
||||
* information relating to OpenGL ES 2.
|
||||
*/
|
||||
public final class GLES2InfoFragment extends ListFragment
|
||||
{
|
||||
private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
List<AboutActivity.AboutFragmentItem> Input = new ArrayList<AboutActivity.AboutFragmentItem>();
|
||||
|
||||
for (Limit limit : Limits)
|
||||
{
|
||||
Log.i("GLES2InfoFragment", "Getting enum " + limit.name);
|
||||
Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
|
||||
}
|
||||
|
||||
// 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()));
|
||||
|
||||
AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
|
||||
rootView.setAdapter(adapter);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* 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.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.about.Limit.Type;
|
||||
import org.dolphinemu.dolphinemu.utils.EGLHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link ListFragment} responsible for displaying
|
||||
* information relating to OpenGL ES 3.
|
||||
*/
|
||||
public final class GLES3InfoFragment extends ListFragment
|
||||
{
|
||||
private final EGLHelper eglHelper = new EGLHelper(EGLHelper.EGL_OPENGL_ES3_BIT_KHR);
|
||||
|
||||
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", 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", 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),
|
||||
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),
|
||||
};
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
List<AboutActivity.AboutFragmentItem> Input = new ArrayList<AboutActivity.AboutFragmentItem>();
|
||||
|
||||
for (Limit limit : Limits)
|
||||
{
|
||||
Log.i("GLES3InfoFragment", "Getting enum " + limit.name);
|
||||
Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
|
||||
}
|
||||
|
||||
// Get extensions manually
|
||||
int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS);
|
||||
StringBuilder extensionsBuilder = new StringBuilder();
|
||||
for (int i = 0; i < numExtensions; i++)
|
||||
{
|
||||
extensionsBuilder.append(eglHelper.glGetStringi(GLES30.GL_EXTENSIONS, i)).append('\n');
|
||||
}
|
||||
Input.add(new AboutActivity.AboutFragmentItem("OpenGL ES 3.0 Extensions", extensionsBuilder.toString()));
|
||||
|
||||
AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
|
||||
rootView.setAdapter(adapter);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* 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.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.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.
|
||||
*/
|
||||
public final class GLInfoFragment extends ListFragment
|
||||
{
|
||||
private final 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),
|
||||
};
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
List<AboutActivity.AboutFragmentItem> Input = new ArrayList<AboutActivity.AboutFragmentItem>();
|
||||
|
||||
for (Limit limit : Limits)
|
||||
{
|
||||
Log.i("GLInfoFragment", "Getting enum " + limit.name);
|
||||
Input.add(new AboutActivity.AboutFragmentItem(limit.name, limit.GetValue(eglHelper)));
|
||||
}
|
||||
|
||||
// Get extensions manually
|
||||
int numExtensions = eglHelper.glGetInteger(GLES30.GL_NUM_EXTENSIONS);
|
||||
StringBuilder extensionsBuilder = new StringBuilder();
|
||||
for (int i = 0; i < numExtensions; i++)
|
||||
{
|
||||
extensionsBuilder.append(eglHelper.glGetStringi(GL10.GL_EXTENSIONS, i)).append('\n');
|
||||
}
|
||||
Input.add(new AboutActivity.AboutFragmentItem("OpenGL Extensions", extensionsBuilder.toString()));
|
||||
|
||||
AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, Input);
|
||||
rootView.setAdapter(adapter);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package org.dolphinemu.dolphinemu.about;
|
||||
|
||||
import org.dolphinemu.dolphinemu.utils.EGLHelper;
|
||||
|
||||
final class Limit
|
||||
{
|
||||
/**
|
||||
* Possible types a Limit can be.
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
/** Generic string */
|
||||
STRING,
|
||||
/** Integer constant */
|
||||
INTEGER,
|
||||
/** Range of integers */
|
||||
INTEGER_RANGE,
|
||||
}
|
||||
|
||||
/** Name of this limit */
|
||||
public final String name;
|
||||
/** The GL constant that represents this limit.*/
|
||||
public final int glEnum;
|
||||
/** The {@link Type} of this limit. */
|
||||
public final Type type;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Name of the limit.
|
||||
* @param glEnum The GL constant that represents this limit.
|
||||
* @param type The {@link Type} of this limit.
|
||||
*/
|
||||
public Limit(String name, int glEnum, Type type)
|
||||
{
|
||||
this.name = name;
|
||||
this.glEnum = glEnum;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the information represented by this limit.
|
||||
*
|
||||
* @param context {@link EGLHelper} context to retrieve the limit with.
|
||||
*
|
||||
* @return the information represented by this limit.
|
||||
*/
|
||||
public String GetValue(EGLHelper context)
|
||||
{
|
||||
if (type == Type.INTEGER)
|
||||
{
|
||||
return Integer.toString(context.glGetInteger(glEnum));
|
||||
}
|
||||
else if (type == Type.INTEGER_RANGE)
|
||||
{
|
||||
int[] data = new int[2];
|
||||
context.getGL().glGetIntegerv(glEnum, data, 0);
|
||||
|
||||
return String.format("[%d, %d]", data[0], data[1]);
|
||||
}
|
||||
|
||||
// If neither of the above type, assume it's a string.
|
||||
return context.glGetString(glEnum);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
/**
|
||||
* Copyright 2013 Dolphin Emulator Project
|
||||
* Licensed under GPLv2
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.egl.EGLContext;
|
||||
import javax.microedition.khronos.egl.EGLDisplay;
|
||||
import javax.microedition.khronos.egl.EGLSurface;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import android.opengl.GLES30;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Utility class that abstracts all the stuff about
|
||||
* EGL initialization out of the way if all that is
|
||||
* wanted is to query the underlying GL API for information.
|
||||
*/
|
||||
public final class EGLHelper
|
||||
{
|
||||
private final EGL10 mEGL;
|
||||
private final EGLDisplay mDisplay;
|
||||
private EGLConfig[] mEGLConfigs;
|
||||
private EGLContext mEGLContext;
|
||||
private EGLSurface mEGLSurface;
|
||||
private GL10 mGL;
|
||||
|
||||
// GL support flags
|
||||
private boolean supportGL;
|
||||
private boolean supportGLES2;
|
||||
private boolean supportGLES3;
|
||||
|
||||
// Renderable type bitmasks
|
||||
public static final int EGL_OPENGL_ES_BIT = 0x0001;
|
||||
public static final int EGL_OPENGL_ES2_BIT = 0x0004;
|
||||
public static final int EGL_OPENGL_BIT = 0x0008;
|
||||
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* <p>
|
||||
* Initializes the underlying {@link EGLSurface} with a width and height of 1.
|
||||
* This is useful if all you need to use this class for is to query information
|
||||
* from specific API contexts.
|
||||
*
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int renderableType)
|
||||
{
|
||||
this(1, 1, renderableType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param width Width of the underlying {@link EGLSurface}.
|
||||
* @param height Height of the underlying {@link EGLSurface}.
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int width, int height, int renderableType)
|
||||
{
|
||||
// Initialize handle to an EGL display.
|
||||
mEGL = (EGL10) EGLContext.getEGL();
|
||||
mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
|
||||
// If a display is present, initialize EGL.
|
||||
if (mDisplay != EGL10.EGL_NO_DISPLAY)
|
||||
{
|
||||
int[] version = new int[2];
|
||||
if (mEGL.eglInitialize(mDisplay, version))
|
||||
{
|
||||
// Detect supported GL APIs, initialize configs, etc.
|
||||
detect();
|
||||
|
||||
// Create context and surface
|
||||
create(width, height, renderableType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e("EGLHelper", "Error initializing EGL.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e("EGLHelper", "Error initializing EGL display.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources associated with this helper.
|
||||
* <p>
|
||||
* This should be called whenever this helper is no longer needed.
|
||||
*/
|
||||
public void closeHelper()
|
||||
{
|
||||
mEGL.eglTerminate(mDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information through EGL.<br/>
|
||||
* <p>
|
||||
* Index 0: Vendor <br/>
|
||||
* Index 1: Version <br/>
|
||||
* Index 2: Renderer <br/>
|
||||
* Index 3: Extensions <br/>
|
||||
*
|
||||
* @return information retrieved through EGL.
|
||||
*/
|
||||
public String[] getEGLInfo()
|
||||
{
|
||||
String[] info = {
|
||||
mGL.glGetString(GL10.GL_VENDOR),
|
||||
mGL.glGetString(GL10.GL_VERSION),
|
||||
mGL.glGetString(GL10.GL_RENDERER),
|
||||
mGL.glGetString(GL10.GL_EXTENSIONS),
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this device supports OpenGL.
|
||||
*
|
||||
* @return true if this device supports OpenGL; false otherwise.
|
||||
*/
|
||||
public boolean supportsOpenGL()
|
||||
{
|
||||
return supportGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this device supports OpenGL ES 2.
|
||||
* <br/>
|
||||
* 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.
|
||||
* <br/>
|
||||
* Note that if this returns true, then OpenGL ES 1 and 2 are also supported.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 3; false otherwise.
|
||||
*/
|
||||
public boolean supportsGLES3()
|
||||
{
|
||||
return supportGLES3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGL10} instance.
|
||||
*
|
||||
* @return the underlying {@link EGL10} instance.
|
||||
*/
|
||||
public EGL10 getEGL()
|
||||
{
|
||||
return mEGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link GL10} instance.
|
||||
*
|
||||
* @return the underlying {@link GL10} instance.
|
||||
*/
|
||||
public GL10 getGL()
|
||||
{
|
||||
return mGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLDisplay}.
|
||||
*
|
||||
* @return the underlying {@link EGLDisplay}
|
||||
*/
|
||||
public EGLDisplay getDisplay()
|
||||
{
|
||||
return mDisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all supported framebuffer configurations for this device.
|
||||
*
|
||||
* @return all supported framebuffer configurations for this device.
|
||||
*/
|
||||
public EGLConfig[] getConfigs()
|
||||
{
|
||||
return mEGLConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLContext}.
|
||||
*
|
||||
* @return the underlying {@link EGLContext}.
|
||||
*/
|
||||
public EGLContext getContext()
|
||||
{
|
||||
return mEGLContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLSurface}.
|
||||
*
|
||||
* @return the underlying {@link EGLSurface}.
|
||||
*/
|
||||
public EGLSurface getSurface()
|
||||
{
|
||||
return mEGLSurface;
|
||||
}
|
||||
|
||||
// Detects the specific kind of GL modes that are supported
|
||||
private boolean detect()
|
||||
{
|
||||
// Get total number of configs available.
|
||||
int[] numConfigs = new int[1];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs))
|
||||
{
|
||||
Log.e("EGLHelper", "Error retrieving number of EGL configs available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now get all the configurations
|
||||
mEGLConfigs = new EGLConfig[numConfigs[0]];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs))
|
||||
{
|
||||
Log.e("EGLHelper", "Error retrieving all EGL configs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mEGLConfigs.length; i++)
|
||||
{
|
||||
int[] attribVal = new int[1];
|
||||
boolean ret = mEGL.eglGetConfigAttrib(mDisplay, mEGLConfigs[i], EGL10.EGL_RENDERABLE_TYPE, attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if ((attribVal[0] & EGL_OPENGL_BIT) != 0)
|
||||
supportGL = true;
|
||||
|
||||
if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0)
|
||||
supportGLES2 = true;
|
||||
|
||||
if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0)
|
||||
supportGLES3 = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates the context and surface.
|
||||
private void create(int width, int height, int renderableType)
|
||||
{
|
||||
int[] attribs = {
|
||||
EGL10.EGL_WIDTH, width,
|
||||
EGL10.EGL_HEIGHT, height,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// Initially we just assume GLES2 will be the default context.
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] ctx_attribs = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// Determine the type of context that will be created
|
||||
// and change the attribute arrays accordingly.
|
||||
switch (renderableType)
|
||||
{
|
||||
case EGL_OPENGL_ES_BIT:
|
||||
ctx_attribs[1] = 1;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_BIT:
|
||||
ctx_attribs[0] = EGL10.EGL_NONE;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES3_BIT_KHR:
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES2_BIT:
|
||||
default: // Fall-back to GLES 2.
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
mEGLContext = mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs);
|
||||
mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs);
|
||||
mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
||||
mGL = (GL10) mEGLContext.getGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetString(int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic constant within {@link GL10}.
|
||||
*
|
||||
* @return the string information represented by {@code glEnum}.
|
||||
*/
|
||||
public String glGetString(int glEnum)
|
||||
{
|
||||
return mGL.glGetString(glEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GLES30#glGetStringi(int, int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* <li>GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic GL constant
|
||||
* @param index The index of the string to return.
|
||||
*
|
||||
* @return the string information represented by {@code glEnum} and {@code index}.
|
||||
*/
|
||||
public String glGetStringi(int glEnum, int index)
|
||||
{
|
||||
return GLES30.glGetStringi(glEnum, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetIntegerv(int, int[], int)
|
||||
*
|
||||
* @param glEnum A symbolic GL constant.
|
||||
*
|
||||
* @return the integer information represented by {@code glEnum}.
|
||||
*/
|
||||
public int glGetInteger(int glEnum)
|
||||
{
|
||||
int[] val = new int[1];
|
||||
mGL.glGetIntegerv(glEnum, val, 0);
|
||||
return val[0];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue