127 changes: 127 additions & 0 deletions Source/Android/res/xml/video_prefs.xml
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Video Settings -->


<!-- Video Enhancements -->
<PreferenceScreen android:title="@string/enhancements">

<ListPreference
android:entries="@array/internalResolutionEntries"
android:entryValues="@array/internalResolutionValues"
android:key="internalResolution"
android:summary="@string/internal_resolution_descrip"
android:title="@string/internal_resolution"/>

<ListPreference
android:entries="@array/anisotropicFilteringEntries"
android:entryValues="@array/anisotropicFilteringValues"
android:key="anisotropicFiltering"
android:summary="@string/anisotropic_filtering_descrip"
android:title="@string/anisotropic_filtering"/>

<CheckBoxPreference
android:defaultValue="true"
android:key="scaledEFBCopy"
android:summary="@string/scaled_efb_copy_descrip"
android:title="@string/scaled_efb_copy"/>

<CheckBoxPreference
android:defaultValue="false"
android:key="perPixelLighting"
android:summary="@string/per_pixel_lighting_descrip"
android:title="@string/per_pixel_lighting"/>

<CheckBoxPreference
android:defaultValue="false"
android:key="forceTextureFiltering"
android:summary="@string/force_texture_filtering_descrip"
android:title="@string/force_texture_filtering"/>

<CheckBoxPreference
android:defaultValue="false"
android:key="disableFog"
android:summary="@string/disable_fog_descrip"
android:title="@string/disable_fog"/>

</PreferenceScreen>

<!-- Video Hacks -->
<PreferenceScreen android:title="@string/hacks">
<PreferenceCategory android:title="@string/embedded_frame_buffer">

<CheckBoxPreference
android:defaultValue="false"
android:key="skipEFBAccess"
android:summary="@string/skip_efb_access_descrip"
android:title="@string/skip_efb_access"/>

<CheckBoxPreference
android:defaultValue="true"
android:key="ignoreFormatChanges"
android:summary="@string/ignore_format_changes_descrip"
android:title="@string/ignore_format_changes"/>

<ListPreference
android:defaultValue="Texture"
android:entries="@array/efbCopyMethodEntries"
android:entryValues="@array/efbCopyMethodValues"
android:key="efbCopyMethod"
android:summary="@string/efb_copy_method_descrip"
android:title="@string/efb_copy_method"/>

</PreferenceCategory>

<!-- Texture Cache -->
<PreferenceCategory android:title="@string/texture_cache">
<ListPreference
android:defaultValue="Low"
android:entries="@array/textureCacheAccuracyEntries"
android:entryValues="@array/textureCacheAccuracyValues"
android:key="textureCacheAccuracy"
android:summary="@string/texture_cache_accuracy_descrip"
android:title="@string/texture_cache_accuracy"/>
</PreferenceCategory>

<!-- External Frame Buffer -->
<PreferenceCategory android:title="@string/external_frame_buffer">
<ListPreference
android:defaultValue="Disabled"
android:entries="@array/externalFrameBufferEntries"
android:entryValues="@array/externalFrameBufferValues"
android:key="externalFrameBuffer"
android:summary="@string/external_frame_buffer_descrip"
android:title="@string/external_frame_buffer"/>
</PreferenceCategory>


<!-- Other Hacks -->
<PreferenceCategory android:title="@string/other">

<CheckBoxPreference
android:defaultValue="false"
android:key="cacheDisplayLists"
android:summary="@string/cache_display_lists_descrip"
android:title="@string/cache_display_lists"/>

<CheckBoxPreference
android:defaultValue="false"
android:key="disableDestinationAlpha"
android:summary="@string/disable_destination_alpha_descrip"
android:title="@string/disable_destination_alpha"/>

<CheckBoxPreference
android:defaultValue="true"
android:key="fastDepthCalculation"
android:summary="@string/fast_depth_calculation_descrip"
android:title="@string/fast_depth_calculation"/>

</PreferenceCategory>
</PreferenceScreen>

<ListPreference
android:key="gpuPref"
android:summary="@string/video_backend_to_use"
android:title="@string/video_backend" />
</PreferenceScreen>
Expand Up @@ -11,6 +11,10 @@
import java.util.ArrayList;
import java.util.List;

import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowserAdapter;
import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowserItem;
import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment;

/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
Expand Down Expand Up @@ -42,7 +46,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa

List<FolderBrowserItem> Input = new ArrayList<FolderBrowserItem>();
Input.add(new FolderBrowserItem(getString(R.string.build_revision), NativeLibrary.GetVersionString(), "", true));
Input.add(new FolderBrowserItem(getString(R.string.supports_gles3), PrefsFragment.SupportsGLES3() ? yes : no, "", true));
Input.add(new FolderBrowserItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no, "", true));

adapter = new FolderBrowserAdapter(m_activity, R.layout.about_layout, Input);
mMainList.setAdapter(adapter);
Expand Down
Expand Up @@ -15,6 +15,10 @@
import java.io.*;
import java.util.List;

import org.dolphinemu.dolphinemu.gamelist.GameListActivity;
import org.dolphinemu.dolphinemu.inputconfig.InputConfigFragment;
import org.dolphinemu.dolphinemu.settings.UserPreferences;

public final class DolphinEmulator<MainActivity> extends Activity
{
static private NativeGLSurfaceView GLview = null;
Expand Down
226 changes: 0 additions & 226 deletions Source/Android/src/org/dolphinemu/dolphinemu/PrefsFragment.java

This file was deleted.

@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.folderbrowser;

import android.app.Activity;
import android.app.Fragment;
Expand All @@ -14,6 +14,10 @@
import java.io.File;
import java.util.*;

import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.gamelist.GameListActivity;

public final class FolderBrowser extends Fragment
{
private Activity m_activity;
Expand Down
@@ -1,4 +1,6 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.folderbrowser;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
Expand All @@ -8,7 +10,7 @@
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
import org.dolphinemu.dolphinemu.R;

public final class FolderBrowserAdapter extends ArrayAdapter<FolderBrowserItem>
{
Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.folderbrowser;

import java.io.File;

Expand Down
@@ -1,8 +1,9 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.gamelist;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
Expand All @@ -13,6 +14,17 @@
import java.util.ArrayList;
import java.util.List;

import org.dolphinemu.dolphinemu.AboutFragment;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.folderbrowser.FolderBrowser;
import org.dolphinemu.dolphinemu.inputconfig.InputConfigAdapter;
import org.dolphinemu.dolphinemu.inputconfig.InputConfigFragment;
import org.dolphinemu.dolphinemu.inputconfig.InputConfigItem;
import org.dolphinemu.dolphinemu.settings.PrefsActivity;
import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter;
import org.dolphinemu.dolphinemu.sidemenu.SideMenuItem;

/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
Expand Down Expand Up @@ -144,11 +156,9 @@ public void SwitchPage(int toPage)
break;

case 2:
{
mCurFragmentNum = 2;
mCurFragment = new PrefsFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit();
{
Intent intent = new Intent(this, PrefsActivity.class);
startActivity(intent);
}
break;

Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.gamelist;

import android.content.Context;
import android.view.LayoutInflater;
Expand All @@ -10,6 +10,8 @@

import java.util.List;

import org.dolphinemu.dolphinemu.R;

public final class GameListAdapter extends ArrayAdapter<GameListItem>
{
private final Context c;
Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.gamelist;

import android.app.Activity;
import android.app.Fragment;
Expand All @@ -19,6 +19,9 @@
import java.util.List;
import java.util.Set;

import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;

/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.gamelist;

import android.content.Context;
import android.graphics.Bitmap;
Expand All @@ -8,6 +8,8 @@
import java.io.IOException;
import java.io.InputStream;

import org.dolphinemu.dolphinemu.NativeLibrary;

public final class GameListItem implements Comparable<GameListItem>
{
private String name;
Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.inputconfig;

import android.content.Context;
import android.view.LayoutInflater;
Expand All @@ -9,6 +9,8 @@

import java.util.List;

import org.dolphinemu.dolphinemu.R;

/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
Expand Down
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.inputconfig;

import android.app.Activity;
import android.app.Fragment;
Expand All @@ -13,6 +13,9 @@
import java.util.ArrayList;
import java.util.List;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.gamelist.GameListActivity;

/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
Expand Down
Expand Up @@ -4,7 +4,9 @@
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.inputconfig;

import org.dolphinemu.dolphinemu.NativeLibrary;

/**
* Represents a controller input item (button, stick, etc).
Expand Down
@@ -0,0 +1,81 @@
/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu.settings;

import org.dolphinemu.dolphinemu.R;

import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.PreferenceFragment;

/**
* Responsible for the loading of the CPU preferences.
*/
public final class CPUSettingsFragment extends PreferenceFragment
{
private Activity m_activity;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.cpu_prefs);

final ListPreference cpuCores = (ListPreference) findPreference("cpuCorePref");

//
// Set valid emulation cores depending on the CPU architecture
// that the Android device is running on.
//
if (Build.CPU_ABI.contains("x86"))
{
cpuCores.setEntries(R.array.emuCoreEntriesX86);
cpuCores.setEntryValues(R.array.emuCoreValuesX86);
}
else if (Build.CPU_ABI.contains("arm"))
{
cpuCores.setEntries(R.array.emuCoreEntriesARM);
cpuCores.setEntryValues(R.array.emuCoreValuesARM);
}
else
{
cpuCores.setEntries(R.array.emuCoreEntriesOther);
cpuCores.setEntryValues(R.array.emuCoreValuesOther);
}
}

@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);

// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try
{
m_activity = activity;
}
catch (ClassCastException e)
{
throw new ClassCastException(activity.toString()
+ " must implement OnGameListZeroListener");
}
}

@Override
public void onDestroy()
{
super.onDestroy();

// When this fragment is destroyed, force the settings to be saved to the ini file.
UserPreferences.SaveConfigToDolphinIni(m_activity);
}
}
@@ -0,0 +1,146 @@
/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu.settings;

import org.dolphinemu.dolphinemu.R;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
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;

/**
* Main activity that manages all of the preference fragments used to display
* the settings to the user.
*/
public final class PrefsActivity extends Activity implements ActionBar.TabListener
{
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide org.dolphinemu.dolphinemu.settings for each of the
* sections. We use a {@link android.support.v4.app.FragmentPagerAdapter} derivative, which will
* keep every loaded fragment in memory. If this becomes too memory intensive, it may be best to
* switch to a {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;

/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.prefs_viewpager);

// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());

// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);

// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
@Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
} );

// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(actionBar.newTab().setText(R.string.cpu_settings).setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.video_settings).setTabListener(this));

}

public void onTabReselected(Tab arg0, FragmentTransaction arg1)
{
// Do nothing.
}

public void onTabSelected(Tab tab, FragmentTransaction ft)
{
// When the given tab is selected, switch to the corresponding page in the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}

public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
// Do nothing.
}

/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the
* sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter
{

public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
}

@Override
public Fragment getItem(int position)
{
switch(position)
{
case 0:
return new CPUSettingsFragment();

case 1:
return new VideoSettingsFragment();

default: // Should never happen.
return null;
}
}

@Override
public int getCount()
{
// Show total pages.
return 2;
}

@Override
public CharSequence getPageTitle(int position)
{
switch(position)
{
case 0:
return getString(R.string.cpu_settings).toUpperCase();

case 1:
return getString(R.string.video_settings).toUpperCase();

default: // Should never happen.
return null;
}
}
}
}
@@ -1,4 +1,12 @@
package org.dolphinemu.dolphinemu;
/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu.settings;

import org.dolphinemu.dolphinemu.NativeLibrary;

import android.content.Context;
import android.content.SharedPreferences;
Expand Down
@@ -0,0 +1,202 @@
/**
* Copyright 2013 Dolphin Emulator Project
* Licensed under GPLv2
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu.settings;

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 org.dolphinemu.dolphinemu.R;

import android.app.Activity;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.PreferenceFragment;

/**
* Responsible for handling the loading of the video preferences.
*/
public final class VideoSettingsFragment extends PreferenceFragment
{
private Activity m_activity;

static public class VersionCheck
{
EGL10 mEGL;
EGLDisplay mEGLDisplay;
EGLConfig[] mEGLConfigs;
EGLConfig mEGLConfig;
EGLContext mEGLContext;
EGLSurface mEGLSurface;
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();
}

public String getVersion()
{
return mGL.glGetString(GL10.GL_VERSION);
}

public String getVendor()
{
return mGL.glGetString(GL10.GL_VENDOR);
}

public String getRenderer()
{
return mGL.glGetString(GL10.GL_RENDERER);
}

private EGLConfig chooseConfig()
{
int[] attribList = new int[] {
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_STENCIL_SIZE, 0,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_NONE
};

// No error checking performed, minimum required code to elucidate logic
// Expand on this logic to be more selective in choosing a configuration
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);

return mEGLConfigs[0]; // Best match is probably the first configuration
}
}

static public boolean SupportsGLES3()
{
VersionCheck mbuffer = new VersionCheck();
String m_GLVersion = mbuffer.getVersion();
String m_GLVendor = mbuffer.getVendor();
String m_GLRenderer = mbuffer.getRenderer();

boolean mSupportsGLES3 = false;

// Check for OpenGL ES 3 support (General case).
if (m_GLVersion != null && (m_GLVersion.contains("OpenGL ES 3.0") || m_GLVersion.equals("OpenGL ES 3.0")))
mSupportsGLES3 = true;

// Checking for OpenGL ES 3 support for certain Qualcomm devices.
if (!mSupportsGLES3 && m_GLVendor != null && m_GLVendor.equals("Qualcomm"))
{
if (m_GLRenderer.contains("Adreno (TM) 3"))
{
int mVStart = m_GLVersion.indexOf("V@") + 2;
int mVEnd = 0;
float mVersion;

for (int a = mVStart; a < m_GLVersion.length(); ++a)
{
if (m_GLVersion.charAt(a) == ' ')
{
mVEnd = a;
break;
}
}

mVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd));

if (mVersion >= 14.0f)
mSupportsGLES3 = true;
}
}
return mSupportsGLES3;
}

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.video_prefs);

//
// Setting valid video backends.
//
final ListPreference videoBackends = (ListPreference) findPreference("gpuPref");
final boolean deviceSupportsGLES3 = SupportsGLES3();

if (deviceSupportsGLES3)
{
videoBackends.setEntries(R.array.videoBackendEntriesGLES3);
videoBackends.setEntryValues(R.array.videoBackendValuesGLES3);
}
else
{
videoBackends.setEntries(R.array.videoBackendEntriesNoGLES3);
videoBackends.setEntryValues(R.array.videoBackendValuesNoGLES3);
}
}

@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);

// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try
{
m_activity = activity;
}
catch (ClassCastException e)
{
throw new ClassCastException(activity.toString()
+ " must implement OnGameListZeroListener");
}
}

@Override
public void onDestroy()
{
super.onDestroy();

// When the fragment is done being used, save the settings to the Dolphin ini file.
UserPreferences.SaveConfigToDolphinIni(m_activity);
}
}
@@ -1,4 +1,4 @@
package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.sidemenu;

import android.content.Context;
import android.view.LayoutInflater;
Expand All @@ -9,6 +9,8 @@

import java.util.List;

import org.dolphinemu.dolphinemu.R;

public final class SideMenuAdapter extends ArrayAdapter<SideMenuItem>
{
private final Context c;
Expand Down
Expand Up @@ -4,7 +4,7 @@
* Refer to the license.txt file included.
*/

package org.dolphinemu.dolphinemu;
package org.dolphinemu.dolphinemu.sidemenu;


/**
Expand Down