From 709ab1feb522d6113dd88d9986653fdd38dbc60e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 03:10:32 -0400 Subject: [PATCH 01/17] [Android] Initial implementation of the new input UI. Testing may be further required. But it should work for the most part. --- .../dolphinemu/DolphinEmulator.java | 2 +- .../dolphinemu/gamelist/GameListActivity.java | 71 +---- .../inputconfig/InputConfigAdapter.java | 70 ----- .../inputconfig/InputConfigFragment.java | 217 --------------- .../inputconfig/InputConfigItem.java | 101 ------- .../settings/InputConfigFragment.java | 252 ++++++++++++++++++ .../dolphinemu/settings/PrefsActivity.java | 51 +++- 7 files changed, 306 insertions(+), 458 deletions(-) delete mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java delete mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java delete mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java create mode 100644 Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java index ca3c637bfb..b7bf23afe3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java @@ -22,7 +22,7 @@ import java.io.*; import java.util.List; import org.dolphinemu.dolphinemu.gamelist.GameListActivity; -import org.dolphinemu.dolphinemu.inputconfig.InputConfigFragment; +import org.dolphinemu.dolphinemu.settings.InputConfigFragment; import org.dolphinemu.dolphinemu.settings.UserPreferences; public final class DolphinEmulator extends Activity diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index b12bff7ebc..503d32ae66 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -27,9 +27,6 @@ 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; @@ -49,16 +46,7 @@ public final class GameListActivity extends Activity private SideMenuAdapter mDrawerAdapter; private ListView mDrawerList; - /** - * Interface defining methods which handle - * the binding of specific key presses within - * the input mapping settings. - */ - public interface OnGameConfigListener - { - boolean onMotionEvent(MotionEvent event); - boolean onKeyEvent(KeyEvent event); - } + /** * Called from the {@link GameListFragment}. @@ -84,8 +72,7 @@ public final class GameListActivity extends Activity dir.add(new SideMenuItem(getString(R.string.game_list), 0)); dir.add(new SideMenuItem(getString(R.string.browse_folder), 1)); dir.add(new SideMenuItem(getString(R.string.settings), 2)); - dir.add(new SideMenuItem(getString(R.string.gamepad_config), 3)); - dir.add(new SideMenuItem(getString(R.string.about), 4)); + dir.add(new SideMenuItem(getString(R.string.about), 3)); mDrawerAdapter = new SideMenuAdapter(this, R.layout.sidemenu, dir); mDrawerList.setAdapter(mDrawerAdapter); @@ -142,25 +129,9 @@ public final class GameListActivity extends Activity recreateFragment(); break; - case 3: // Gamepad settings - { - InputConfigAdapter adapter = ((InputConfigFragment)mCurFragment).getAdapter(); - for (int a = 0; a < adapter.getCount(); ++a) - { - InputConfigItem o = adapter.getItem(a); - String config = o.getConfig(); - String bind = o.getBind(); - String ConfigValues[] = config.split("-"); - String Key = ConfigValues[0]; - String Value = ConfigValues[1]; - NativeLibrary.SetConfig("Dolphin.ini", Key, Value, bind); - } - } - break; - case 0: // Game List case 2: // Settings - case 4: // About + case 3: // About /* Do Nothing */ break; } @@ -197,16 +168,6 @@ public final class GameListActivity extends Activity case 3: { mCurFragmentNum = 3; - mCurFragment = new InputConfigFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); - invalidateOptionsMenu(); - } - break; - - case 4: - { - mCurFragmentNum = 4; mCurFragment = new AboutFragment(); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); @@ -322,30 +283,4 @@ public final class GameListActivity extends Activity { SwitchPage(0); } - - // Gets move(triggers, joystick) events - @Override - public boolean dispatchGenericMotionEvent(MotionEvent event) - { - if (mCurFragmentNum == 3) - { - if (((OnGameConfigListener)mCurFragment).onMotionEvent(event)) - return true; - } - - return super.dispatchGenericMotionEvent(event); - } - - // Gets button presses - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - if (mCurFragmentNum == 3) - { - if (((OnGameConfigListener)mCurFragment).onKeyEvent(event)) - return true; - } - - return super.dispatchKeyEvent(event); - } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java deleted file mode 100644 index 318075ec40..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import java.util.List; - -import org.dolphinemu.dolphinemu.R; - -/** - * The adapter backing the input mapping configuration. - *

- * Responsible for handling the list items. - */ -public final class InputConfigAdapter extends ArrayAdapter -{ - private final Context c; - private final int id; - private final List items; - - public InputConfigAdapter(Context context, int textViewResourceId, List objects) - { - super(context, textViewResourceId, objects); - c = context; - id = textViewResourceId; - items = objects; - } - - @Override - public InputConfigItem getItem(int i) - { - return items.get(i); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) - { - View v = convertView; - if (v == null) - { - LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(id, parent, false); - } - - final InputConfigItem item = items.get(position); - if (item != null) - { - TextView title = (TextView) v.findViewById(R.id.FolderTitle); - TextView subtitle = (TextView) v.findViewById(R.id.FolderSubTitle); - - if (title != null) - title.setText(item.getName()); - - if (subtitle != null) - subtitle.setText(item.getBind()); - } - - return v; - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java deleted file mode 100644 index dd91b952c7..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigFragment.java +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import android.app.Activity; -import android.app.Fragment; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.view.*; -import android.widget.AdapterView; -import android.widget.ListView; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; - -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.gamelist.GameListActivity; - -/** - * The {@link Fragment} responsible for implementing the functionality - * within the input control mapping config. - */ -public final class InputConfigFragment extends Fragment - implements GameListActivity.OnGameConfigListener -{ - private Activity m_activity; - private ListView mDrawerList; - private InputConfigAdapter adapter; - private int configPosition = 0; - private boolean Configuring = false; - private boolean firstEvent = true; - - /** - * Gets the descriptor for the given {@link InputDevice}. - * - * @param input The {@link InputDevice} to get the descriptor of. - * - * @return the descriptor for the given {@link InputDevice}. - */ - public static String getInputDesc(InputDevice input) - { - if (input == null) - return "null"; // Happens when the inputdevice is from an unknown source - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - { - return input.getDescriptor(); - } - else - { - List motions = input.getMotionRanges(); - String fakeid = ""; - - for (InputDevice.MotionRange range : motions) - fakeid += range.getAxis(); - - return fakeid; - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) - { - List Input = new ArrayList(); - Input.add(new InputConfigItem(getString(R.string.button_a), "Android-InputA")); - Input.add(new InputConfigItem(getString(R.string.button_b), "Android-InputB")); - Input.add(new InputConfigItem(getString(R.string.button_start), "Android-InputStart")); - Input.add(new InputConfigItem(getString(R.string.button_x), "Android-InputX")); - Input.add(new InputConfigItem(getString(R.string.button_y), "Android-InputY")); - Input.add(new InputConfigItem(getString(R.string.button_z), "Android-InputZ")); - Input.add(new InputConfigItem(getString(R.string.dpad_up), "Android-DPadUp")); - Input.add(new InputConfigItem(getString(R.string.dpad_down), "Android-DPadDown")); - Input.add(new InputConfigItem(getString(R.string.dpad_left), "Android-DPadLeft")); - Input.add(new InputConfigItem(getString(R.string.dpad_right), "Android-DPadRight")); - Input.add(new InputConfigItem(getString(R.string.main_stick_up), "Android-MainUp")); - Input.add(new InputConfigItem(getString(R.string.main_stick_down), "Android-MainDown")); - Input.add(new InputConfigItem(getString(R.string.main_stick_left), "Android-MainLeft")); - Input.add(new InputConfigItem(getString(R.string.main_stick_right), "Android-MainRight")); - Input.add(new InputConfigItem(getString(R.string.c_stick_up), "Android-CStickUp")); - Input.add(new InputConfigItem(getString(R.string.c_stick_down), "Android-CStickDown")); - Input.add(new InputConfigItem(getString(R.string.c_stick_left), "Android-CStickLeft")); - Input.add(new InputConfigItem(getString(R.string.c_stick_right), "Android-CStickRight")); - Input.add(new InputConfigItem(getString(R.string.trigger_left), "Android-InputL")); - Input.add(new InputConfigItem(getString(R.string.trigger_right), "Android-InputR")); - - adapter = new InputConfigAdapter(m_activity, R.layout.folderbrowser, Input); - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - mDrawerList = (ListView) rootView.findViewById(R.id.gamelist); - - mDrawerList.setAdapter(adapter); - mDrawerList.setOnItemClickListener(mMenuItemClickListener); - return mDrawerList; - } - - private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener() - { - public void onItemClick(AdapterView parent, View view, int position, long id) - { - InputConfigItem o = adapter.getItem(position); - - Toast.makeText(m_activity, getString(R.string.press_button_to_config, o.getName()), Toast.LENGTH_SHORT).show(); - configPosition = position; - Configuring = true; - firstEvent = true; - } - }; - - private static ArrayList m_values = new ArrayList(); - - private void AssignBind(String bind) - { - InputConfigItem o = adapter.getItem(configPosition); - adapter.remove(o); - o.setBind(bind); - adapter.insert(o, configPosition); - } - - /** - * Gets the current {@link InputConfigAdapter} - * - * @return the current {@link InputConfigAdapter}. - */ - public InputConfigAdapter getAdapter() - { - return adapter; - } - - // Called from GameListActivity - public boolean onMotionEvent(MotionEvent event) - { - if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) - return false; - - InputDevice input = event.getDevice(); - List motions = input.getMotionRanges(); - if (Configuring) - { - if (firstEvent) - { - m_values.clear(); - - for (InputDevice.MotionRange range : motions) - { - m_values.add(event.getAxisValue(range.getAxis())); - } - - firstEvent = false; - } - else - { - for (int a = 0; a < motions.size(); ++a) - { - InputDevice.MotionRange range = motions.get(a); - - if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f)) - { - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-"); - Configuring = false; - } - else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) - { - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+"); - Configuring = false; - } - } - } - } - return true; - } - - // Called from GameListActivity - public boolean onKeyEvent(KeyEvent event) - { - Log.w("InputConfigFragment", "Got Event " + event.getAction()); - switch (event.getAction()) - { - case KeyEvent.ACTION_DOWN: - case KeyEvent.ACTION_UP: - if (Configuring) - { - InputDevice input = event.getDevice(); - AssignBind("Device '" + InputConfigFragment.getInputDesc(input) + "'-Button " + event.getKeyCode()); - Configuring = false; - return true; - } - - default: - break; - } - - return false; - } - - @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"); - } - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java b/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java deleted file mode 100644 index fc11c7c347..0000000000 --- a/Source/Android/src/org/dolphinemu/dolphinemu/inputconfig/InputConfigItem.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2 - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.inputconfig; - -import org.dolphinemu.dolphinemu.NativeLibrary; - -/** - * Represents a controller input item (button, stick, etc). - */ -public final class InputConfigItem implements Comparable -{ - private String m_name; - private String m_Config; - private String m_bind; - - private void Init(String name, String config, String defaultBind) - { - m_name = name; - m_Config = config; - String ConfigValues[] = m_Config.split("-"); - String Key = ConfigValues[0]; - String Value = ConfigValues[1]; - m_bind = NativeLibrary.GetConfig("Dolphin.ini", Key, Value, defaultBind); - } - - /** - * Constructor - * - * @param name Name of the input config item. - * @param config Name of the key in the configuration file that this control modifies. - * @param defaultBind Default binding to fall back upon if binding fails. - */ - public InputConfigItem(String name, String config, String defaultBind) - { - Init(name, config, defaultBind); - } - - /** - * Constructor that creates an InputConfigItem - * that has a default binding of "None". - * - * @param name Name of the input config item. - * @param config Name of the key in the configuration file that this control modifies. - */ - public InputConfigItem(String name, String config) - { - Init(name, config, "None"); - } - - /** - * Gets the name of this InputConfigItem. - * - * @return the name of this InputConfigItem - */ - public String getName() - { - return m_name; - } - - /** - * Gets the config key this InputConfigItem modifies. - * - * @return the config key this InputConfigItem modifies. - */ - public String getConfig() - { - return m_Config; - } - - /** - * Gets the currently set binding of this InputConfigItem. - * - * @return the currently set binding of this InputConfigItem - */ - public String getBind() - { - return m_bind; - } - - /** - * Sets a new binding for this InputConfigItem. - * - * @param bind The new binding. - */ - public void setBind(String bind) - { - m_bind = bind; - } - - public int compareTo(InputConfigItem o) - { - if (this.m_name != null) - return this.m_name.toLowerCase().compareTo(o.getName().toLowerCase()); - else - throw new IllegalArgumentException(); - } -} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java new file mode 100644 index 0000000000..5a3511b39d --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -0,0 +1,252 @@ +/** + * Copyright 2013 Dolphin Emulator Project + * Licensed under GPLv2 + * Refer to the license.txt file included. + */ + +package org.dolphinemu.dolphinemu.settings; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; +import android.util.Log; +import android.view.*; + +import java.util.ArrayList; +import java.util.List; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; + +/** + * The {@link Fragment} responsible for implementing the functionality + * within the input control mapping config. + */ +public final class InputConfigFragment extends PreferenceFragment + //implements PrefsActivity.OnGameConfigListener +{ + private Activity m_activity; + private boolean firstEvent = true; + private static ArrayList m_values = new ArrayList(); + protected MotionAlertDialog dialog; + + /** + * Gets the descriptor for the given {@link InputDevice}. + * + * @param input The {@link InputDevice} to get the descriptor of. + * + * @return the descriptor for the given {@link InputDevice}. + */ + public static String getInputDesc(InputDevice input) + { + if (input == null) + return "null"; // Happens when the inputdevice is from an unknown source + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) + { + return input.getDescriptor(); + } + else + { + List motions = input.getMotionRanges(); + String fakeid = ""; + + for (InputDevice.MotionRange range : motions) + fakeid += range.getAxis(); + + return fakeid; + } + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + // Expand the preferences from the XML. + addPreferencesFromResource(R.xml.input_prefs); + + // Set the summary messages of the preferences to whatever binding + // is currently set within the Dolphin config. + final String[] keys = + { + "InputA", "InputB", "InputX", "InputY", "InputZ", "InputStart", + "DPadUp", "DPadDown", "DPadLeft", "DPadRight", + "MainUp", "MainDown", "MainLeft", "MainRight", + "CStickUp", "CStickDown", "CStickLeft", "CStickRight", + "InputL", "InputR", + }; + + Preference pref; + for (String key : keys) + { + String binding = NativeLibrary.GetConfig("Dolphin.ini", "Android", key, "None"); + pref = findPreference(key); + pref.setSummary(binding); + } + } + + @Override + public boolean onPreferenceTreeClick(final PreferenceScreen screen, final Preference pref) + { + // Begin the creation of the input alert. + dialog = new MotionAlertDialog(m_activity); + + // Set the key listener + dialog.setOnKeyEventListener(new MotionAlertDialog.OnKeyEventListener() + { + public boolean onKey(KeyEvent event) + { + Log.d("InputConfigFragment", "Received key event: " + event.getAction()); + switch (event.getAction()) + { + case KeyEvent.ACTION_DOWN: + case KeyEvent.ACTION_UP: + InputDevice input = event.getDevice(); + String bindStr = "Device '" + getInputDesc(input) + "'-Button " + event.getKeyCode(); + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + dialog.dismiss(); + return true; + + default: + break; + } + + return false; + } + }); + + // Set the motion event listener. + dialog.setOnMotionEventListener(new MotionAlertDialog.OnMotionEventListener() + { + public boolean onMotion(MotionEvent event) + { + Log.d("InputConfigFragment", "Received motion event: " + event.getAction()); + if (event == null || (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0) + return false; + + InputDevice input = event.getDevice(); + List motions = input.getMotionRanges(); + if (firstEvent) + { + m_values.clear(); + + for (InputDevice.MotionRange range : motions) + { + m_values.add(event.getAxisValue(range.getAxis())); + } + + firstEvent = false; + } + else + { + for (int a = 0; a < motions.size(); ++a) + { + InputDevice.MotionRange range = motions.get(a); + + if (m_values.get(a) > (event.getAxisValue(range.getAxis()) + 0.5f)) + { + String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-"; + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + } + else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) + { + String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+"; + NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); + pref.setSummary(bindStr); + } + } + } + + dialog.dismiss(); + return true; + } + }); + + // Set the cancel button. + dialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), new AlertDialog.OnClickListener() + { + public void onClick(DialogInterface dialog, int which) + { + // Do nothing. This just makes the cancel button appear. + } + }); + + // Set the title and description message. + dialog.setTitle(R.string.input_binding); + dialog.setMessage(getString(R.string.input_binding_descrip)); + + // Don't allow the dialog to close when a user taps + // outside of it. They must press cancel or provide an input. + dialog.setCanceledOnTouchOutside(false); + + // Everything is set, show the dialog. + dialog.show(); + return true; + } + + @Override + public void onAttach(Activity activity) + { + super.onAttach(activity); + + // Cache the activity instance. + m_activity = activity; + } + + + /** + * {@link AlertDialog} class derivative that can handle motion events. + */ + protected static final class MotionAlertDialog extends AlertDialog implements PrefsActivity.OnMotionConfigListener + { + private OnKeyEventListener keyListener; + private OnMotionEventListener motionListener; + + public MotionAlertDialog(Context ctx) + { + super(ctx); + } + + public interface OnKeyEventListener + { + boolean onKey(KeyEvent event); + } + + public interface OnMotionEventListener + { + boolean onMotion(MotionEvent event); + } + + public void setOnKeyEventListener(OnKeyEventListener listener) + { + this.keyListener = listener; + } + + public void setOnMotionEventListener(OnMotionEventListener listener) + { + this.motionListener = listener; + } + + @Override + public boolean onKeyDown(int keycode, KeyEvent event) + { + return keyListener.onKey(event); + } + + @Override + public boolean onMotionEvent(MotionEvent event) + { + return motionListener.onMotion(event); + } + } +} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index 08685fa008..cde60e7a8c 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -17,6 +17,8 @@ import android.app.FragmentTransaction; import android.os.Bundle; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; +import android.view.KeyEvent; +import android.view.MotionEvent; /** * Main activity that manages all of the preference fragments used to display @@ -24,6 +26,16 @@ import android.support.v4.view.ViewPager; */ public final class PrefsActivity extends Activity implements ActionBar.TabListener { + /** + * Interface defining methods which handle + * the binding of specific key presses within + * the input mapping settings. + */ + public interface OnMotionConfigListener + { + boolean onMotionEvent(MotionEvent event); + } + /** * 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 @@ -72,6 +84,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // 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.input_settings).setTabListener(this)); actionBar.addTab(actionBar.newTab().setText(R.string.video_settings).setTabListener(this)); } @@ -91,6 +104,36 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // Do nothing. } + + // TODO: Eventually make correct implementations of these. + // Gets move(triggers, joystick) events + @Override + public boolean dispatchGenericMotionEvent(MotionEvent event) + { + if (mViewPager.getCurrentItem() == 1) + { + InputConfigFragment fragment = (InputConfigFragment) getFragmentManager().findFragmentByTag("android:switcher:"+R.id.pager+":1"); + if (fragment.dialog != null && ((OnMotionConfigListener) fragment.dialog).onMotionEvent(event)) + return true; + } + + return super.dispatchGenericMotionEvent(event); + } + + // Gets button presses + @Override + public boolean dispatchKeyEvent(KeyEvent event) + { + if (mViewPager.getCurrentItem() == 1 && event.getKeyCode() != KeyEvent.KEYCODE_BACK) + { + InputConfigFragment fragment = (InputConfigFragment) getFragmentManager().findFragmentByTag("android:switcher:"+R.id.pager+":1"); + if (fragment.dialog != null && fragment.dialog.onKeyDown(event.getKeyCode(), event)) + return true; + } + + return super.dispatchKeyEvent(event); + } + /** * A {@link FragmentPagerAdapter} that returns a fragment * corresponding to one of the sections/tabs/pages. @@ -111,6 +154,9 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen return new CPUSettingsFragment(); case 1: + return new InputConfigFragment(); + + case 2: return new VideoSettingsFragment(); default: // Should never happen. @@ -122,7 +168,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen public int getCount() { // Show total pages. - return 2; + return 3; } @Override @@ -134,6 +180,9 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen return getString(R.string.cpu_settings).toUpperCase(); case 1: + return getString(R.string.input_settings).toUpperCase(); + + case 2: return getString(R.string.video_settings).toUpperCase(); default: // Should never happen. From 6c0c4603204d4e90e0c0253dae56d3afea728c53 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 03:13:00 -0400 Subject: [PATCH 02/17] [Android] Woops forgot to commit the new resource strings. --- Source/Android/res/values-ja/strings.xml | 4 ++++ Source/Android/res/values/strings.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index 12594ca2ac..73ef858a00 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -31,6 +31,9 @@ クリックされたファイル: + 入力設定 + 入力バインディング + このコントロールにバインドするための入力を移動または押してください。 Aボタン Bボタン スタートボタン @@ -115,6 +118,7 @@ はい いいえ + キャンセル 無効 その他 diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index dac787e4bc..1abeb4992d 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -31,6 +31,9 @@ File clicked: + Input + Input Binding + Press or move an input to bind it to this control. Button A Button B Button Start @@ -115,6 +118,7 @@ Yes No + Cancel Disabled Other From 28008814a74762c746c56e93a10c3016ed96f7a5 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 03:16:05 -0400 Subject: [PATCH 03/17] [Android] Apparently I also forgot to commit the input menu layout. --- Source/Android/res/xml/input_prefs.xml | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Source/Android/res/xml/input_prefs.xml diff --git a/Source/Android/res/xml/input_prefs.xml b/Source/Android/res/xml/input_prefs.xml new file mode 100644 index 0000000000..daddf93e3d --- /dev/null +++ b/Source/Android/res/xml/input_prefs.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 786f09b1fa002393fec3507366b3f3d89b4e3b2b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 23:47:51 -0400 Subject: [PATCH 04/17] [Android] Document the event callback system used in the Settings menu in large detail. --- .../dolphinemu/settings/PrefsActivity.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index cde60e7a8c..e45281e40d 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -1,4 +1,4 @@ -/** +/** * Copyright 2013 Dolphin Emulator Project * Licensed under GPLv2 * Refer to the license.txt file included. @@ -104,6 +104,36 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // Do nothing. } + // How the event callback system works. The way dispatchGenericMotionEvent and dispatchKeyEvent + // work, is that they intercept ANY motion event or key event (respectively) and then follow the + // defined behavior in the overridden method. + // + // Now, to make this easier to understand, consider the following analogy: + // + // This class is a hydro-electric station that provides 'electricity' (key/motion events) + // to a series of 'houses' (in this case, fragments that implement the OnMotionConfigListener interface, or + // fragments that are housed within the ViewPager of this activity. So in a sense, the handline of + // key/motion events 'flows' from this class to the fragments housed in the ViewPager. + // + // While every single key/motion event is intercepted, every single intercepted event DOES NOT + // have to be handled by every fragment. Consider the fact that the only reason the InputConfigFragment + // requires the use of these, is so key binding events can be caught and handled. Other fragments + // have no need to use this. + // + // Consider the following representation of this activity as a ViewPager + // + // ╔══PrefsActivity═════════════════════════════════════╗ + // ║ ╔══════════╗ ╔══════════╗ ╔══════════╗ ║ + // ║ ║ Fragment ║ ║ Fragment ║ ║ Fragment ║ ║ + // ║ ║ 0 ║ ║ 1 ║ ║ 2 ║ ║ + // ║ ╚══════════╝ ╚══════════╝ ╚══════════╝ ║ + // ╚════════════════════════════════════════════════════╝ + // + // Since fragments are NOT considered to be fully-fledged activities, but more of as a UI 'component' + // they do not have dispatch methods like Activities to override. So, in order to simulate this, + // simply implement the OnMotionConfigListener interface in the fragment, and then add the + // conditions of when it's acceptable to call those implemented methods in the fragment to + // the appropriate dispatch method. // TODO: Eventually make correct implementations of these. // Gets move(triggers, joystick) events From 9dfb6dfd7fb048e3690c8c21ea62be2c7b74eba2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 23:49:51 -0400 Subject: [PATCH 05/17] [Android] Fixed a typo in the event callback system documentation. --- .../src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index e45281e40d..aae92efc8a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -112,7 +112,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // // This class is a hydro-electric station that provides 'electricity' (key/motion events) // to a series of 'houses' (in this case, fragments that implement the OnMotionConfigListener interface, or - // fragments that are housed within the ViewPager of this activity. So in a sense, the handline of + // fragments that are housed within the ViewPager of this activity. So in a sense, the handling of // key/motion events 'flows' from this class to the fragments housed in the ViewPager. // // While every single key/motion event is intercepted, every single intercepted event DOES NOT From db355b21d2c5a0ce383b3e711fd1cb425c5878f5 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 25 Aug 2013 23:57:53 -0400 Subject: [PATCH 06/17] [Android] My bad, somehow the Java file in the previous commit got encoded with UTF8+BOM. --- .../src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index aae92efc8a..6f8195b994 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -1,4 +1,4 @@ -/** +/** * Copyright 2013 Dolphin Emulator Project * Licensed under GPLv2 * Refer to the license.txt file included. From 07ea7710127026dde8bd188b998459fe044e05de Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 26 Aug 2013 08:06:28 -0400 Subject: [PATCH 07/17] [Android] Finish documenting the native functions in NativeLibrary.java. --- .../dolphinemu/dolphinemu/NativeLibrary.java | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index dedd824c87..6b61393166 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -15,10 +15,33 @@ import android.view.Surface; */ public final class NativeLibrary { + /** + * Handles touch events. + * + * @param Action Mask for the action being performed. + * @param X Location on the screen's X-axis that the touch event occurred. + * @param Y Location on the screen's Y-axis that the touch event occurred. + */ public static native void onTouchEvent(int Action, float X, float Y); + + /** + * Handles button press events for a gamepad. + * + * @param Device The input descriptor of the gamepad. + * @param Button Key code identifying which button was pressed. + * @param Action Mask identifying which action is happing (button pressed down, or button released). + */ public static native void onGamePadEvent(String Device, int Button, int Action); + + /** + * Handles gamepad movement events. + * + * @param Device The device ID of the gamepad. + * @param Axis The axis ID + * @param Value The value of the axis represented by the given ID. + */ public static native void onGamePadMoveEvent(String Device, int Axis, float Value); - + /** * Gets a value from a key in the given ini-based config file. * @@ -30,7 +53,7 @@ public final class NativeLibrary * @return the value stored at the key, or a default value if it doesn't exist. */ public static native String GetConfig(String configFile, String Section, String Key, String Default); - + /** * Sets a value to a key in the given ini config file. * @@ -40,14 +63,14 @@ public final class NativeLibrary * @param Value The string to set the ini key to. */ public static native void SetConfig(String configFile, String Section, String Key, String Value); - + /** * Sets the filename to be run during emulation. * * @param filename The filename to be run during emulation. */ public static native void SetFilename(String filename); - + /** * Sets the dimensions of the rendering window. * @@ -55,7 +78,7 @@ public final class NativeLibrary * @param height The new height of the rendering window (in pixels). */ public static native void SetDimensions(int width, int height); - + /** * Gets the embedded banner within the given ISO/ROM. * @@ -64,7 +87,7 @@ public final class NativeLibrary * @return an integer array containing the color data for the banner. */ public static native int[] GetBanner(String filename); - + /** * Gets the embedded title of the given ISO/ROM. * @@ -73,7 +96,7 @@ public final class NativeLibrary * @return the embedded title of the ISO/ROM. */ public static native String GetTitle(String filename); - + /** * Gets the Dolphin version string. * @@ -87,13 +110,13 @@ public final class NativeLibrary * @param surf The surface to render to. */ public static native void Run(Surface surf); - + /** Unpauses emulation from a paused state. */ public static native void UnPauseEmulation(); - + /** Pauses emulation. */ public static native void PauseEmulation(); - + /** Stops emulation. */ public static native void StopEmulation(); From 08153387c5d739b305dd6e2daf85db251e1891aa Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 26 Aug 2013 08:57:52 -0400 Subject: [PATCH 08/17] [Android] Greatly simplify the input handling for the button mapping settings. Now input handling is directly in the fragment. --- .../settings/InputConfigFragment.java | 20 ++++-- .../dolphinemu/settings/PrefsActivity.java | 72 ------------------- 2 files changed, 13 insertions(+), 79 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java index 5a3511b39d..686aa4b4c7 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -207,7 +207,7 @@ public final class InputConfigFragment extends PreferenceFragment /** * {@link AlertDialog} class derivative that can handle motion events. */ - protected static final class MotionAlertDialog extends AlertDialog implements PrefsActivity.OnMotionConfigListener + protected static final class MotionAlertDialog extends AlertDialog { private OnKeyEventListener keyListener; private OnMotionEventListener motionListener; @@ -236,17 +236,23 @@ public final class InputConfigFragment extends PreferenceFragment { this.motionListener = listener; } - + @Override - public boolean onKeyDown(int keycode, KeyEvent event) + public boolean dispatchKeyEvent(KeyEvent event) { - return keyListener.onKey(event); + if (keyListener.onKey(event)) + return true; + + return super.dispatchKeyEvent(event); } - + @Override - public boolean onMotionEvent(MotionEvent event) + public boolean dispatchGenericMotionEvent(MotionEvent event) { - return motionListener.onMotion(event); + if (motionListener.onMotion(event)) + return true; + + return super.dispatchGenericMotionEvent(event); } } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java index 6f8195b994..dc75de2550 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java @@ -17,8 +17,6 @@ import android.app.FragmentTransaction; import android.os.Bundle; import android.support.v13.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; -import android.view.KeyEvent; -import android.view.MotionEvent; /** * Main activity that manages all of the preference fragments used to display @@ -26,16 +24,6 @@ import android.view.MotionEvent; */ public final class PrefsActivity extends Activity implements ActionBar.TabListener { - /** - * Interface defining methods which handle - * the binding of specific key presses within - * the input mapping settings. - */ - public interface OnMotionConfigListener - { - boolean onMotionEvent(MotionEvent event); - } - /** * 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 @@ -104,66 +92,6 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen // Do nothing. } - // How the event callback system works. The way dispatchGenericMotionEvent and dispatchKeyEvent - // work, is that they intercept ANY motion event or key event (respectively) and then follow the - // defined behavior in the overridden method. - // - // Now, to make this easier to understand, consider the following analogy: - // - // This class is a hydro-electric station that provides 'electricity' (key/motion events) - // to a series of 'houses' (in this case, fragments that implement the OnMotionConfigListener interface, or - // fragments that are housed within the ViewPager of this activity. So in a sense, the handling of - // key/motion events 'flows' from this class to the fragments housed in the ViewPager. - // - // While every single key/motion event is intercepted, every single intercepted event DOES NOT - // have to be handled by every fragment. Consider the fact that the only reason the InputConfigFragment - // requires the use of these, is so key binding events can be caught and handled. Other fragments - // have no need to use this. - // - // Consider the following representation of this activity as a ViewPager - // - // ╔══PrefsActivity═════════════════════════════════════╗ - // ║ ╔══════════╗ ╔══════════╗ ╔══════════╗ ║ - // ║ ║ Fragment ║ ║ Fragment ║ ║ Fragment ║ ║ - // ║ ║ 0 ║ ║ 1 ║ ║ 2 ║ ║ - // ║ ╚══════════╝ ╚══════════╝ ╚══════════╝ ║ - // ╚════════════════════════════════════════════════════╝ - // - // Since fragments are NOT considered to be fully-fledged activities, but more of as a UI 'component' - // they do not have dispatch methods like Activities to override. So, in order to simulate this, - // simply implement the OnMotionConfigListener interface in the fragment, and then add the - // conditions of when it's acceptable to call those implemented methods in the fragment to - // the appropriate dispatch method. - - // TODO: Eventually make correct implementations of these. - // Gets move(triggers, joystick) events - @Override - public boolean dispatchGenericMotionEvent(MotionEvent event) - { - if (mViewPager.getCurrentItem() == 1) - { - InputConfigFragment fragment = (InputConfigFragment) getFragmentManager().findFragmentByTag("android:switcher:"+R.id.pager+":1"); - if (fragment.dialog != null && ((OnMotionConfigListener) fragment.dialog).onMotionEvent(event)) - return true; - } - - return super.dispatchGenericMotionEvent(event); - } - - // Gets button presses - @Override - public boolean dispatchKeyEvent(KeyEvent event) - { - if (mViewPager.getCurrentItem() == 1 && event.getKeyCode() != KeyEvent.KEYCODE_BACK) - { - InputConfigFragment fragment = (InputConfigFragment) getFragmentManager().findFragmentByTag("android:switcher:"+R.id.pager+":1"); - if (fragment.dialog != null && fragment.dialog.onKeyDown(event.getKeyCode(), event)) - return true; - } - - return super.dispatchKeyEvent(event); - } - /** * A {@link FragmentPagerAdapter} that returns a fragment * corresponding to one of the sections/tabs/pages. From ba274368f8455849d419ce686f36361841e7b891 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 26 Aug 2013 11:58:51 -0400 Subject: [PATCH 09/17] [Android] Make the dialog variable in InputConfigFragment a local variable in onPreferenceTreeClick. With the new input UI, this doesn't need to be accessible to other classes. Also change the documentation of the custom dialog class. --- .../dolphinemu/settings/InputConfigFragment.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java index 686aa4b4c7..8c9f6f0be4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -35,7 +35,6 @@ public final class InputConfigFragment extends PreferenceFragment private Activity m_activity; private boolean firstEvent = true; private static ArrayList m_values = new ArrayList(); - protected MotionAlertDialog dialog; /** * Gets the descriptor for the given {@link InputDevice}. @@ -47,7 +46,7 @@ public final class InputConfigFragment extends PreferenceFragment public static String getInputDesc(InputDevice input) { if (input == null) - return "null"; // Happens when the inputdevice is from an unknown source + return "null"; // Happens when the InputDevice is from an unknown source if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { @@ -97,7 +96,7 @@ public final class InputConfigFragment extends PreferenceFragment public boolean onPreferenceTreeClick(final PreferenceScreen screen, final Preference pref) { // Begin the creation of the input alert. - dialog = new MotionAlertDialog(m_activity); + final MotionAlertDialog dialog = new MotionAlertDialog(m_activity); // Set the key listener dialog.setOnKeyEventListener(new MotionAlertDialog.OnKeyEventListener() @@ -205,7 +204,9 @@ public final class InputConfigFragment extends PreferenceFragment /** - * {@link AlertDialog} class derivative that can handle motion events. + * {@link AlertDialog} class derivative that allows the motion listener + * to be set anonymously, so the creation of an explicit class for + * providing functionality is not necessary. */ protected static final class MotionAlertDialog extends AlertDialog { From e12c66b6cf0276c85b1dcb1a255c6c5c24647711 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 26 Aug 2013 12:56:35 -0400 Subject: [PATCH 10/17] [Android] Only dismiss the input dialog when an input is registered. Before it would dismiss upon the first event. Fixes a bug where control sticks wouldn't register because of the AlertDialog closing immediately after the "if (firstEvent)" branch. --- .../dolphinemu/dolphinemu/settings/InputConfigFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java index 8c9f6f0be4..5340fb9b6c 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -156,17 +156,18 @@ public final class InputConfigFragment extends PreferenceFragment String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "-"; NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); pref.setSummary(bindStr); + dialog.dismiss(); } else if (m_values.get(a) < (event.getAxisValue(range.getAxis()) - 0.5f)) { String bindStr = "Device '" + InputConfigFragment.getInputDesc(input) + "'-Axis " + range.getAxis() + "+"; NativeLibrary.SetConfig("Dolphin.ini", "Android", pref.getKey(), bindStr); pref.setSummary(bindStr); + dialog.dismiss(); } } } - dialog.dismiss(); return true; } }); From 670b0284929bae65c08e4d6c12c210d89d068d3c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 26 Aug 2013 13:19:06 -0400 Subject: [PATCH 11/17] [Android] Remove the explicit key event listener from InputConfigFragment. The AlertDialog class has a key listener built into it. Also documented the methods/interfaces in MotionAlertDialog. --- .../settings/InputConfigFragment.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java index 5340fb9b6c..8914c496b9 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java @@ -99,9 +99,9 @@ public final class InputConfigFragment extends PreferenceFragment final MotionAlertDialog dialog = new MotionAlertDialog(m_activity); // Set the key listener - dialog.setOnKeyEventListener(new MotionAlertDialog.OnKeyEventListener() + dialog.setOnKeyListener(new AlertDialog.OnKeyListener() { - public boolean onKey(KeyEvent event) + public boolean onKey(DialogInterface dlg, int keyCode, KeyEvent event) { Log.d("InputConfigFragment", "Received key event: " + event.getAction()); switch (event.getAction()) @@ -211,38 +211,42 @@ public final class InputConfigFragment extends PreferenceFragment */ protected static final class MotionAlertDialog extends AlertDialog { - private OnKeyEventListener keyListener; private OnMotionEventListener motionListener; + /** + * Constructor + * + * @param ctx context to use this dialog in. + */ public MotionAlertDialog(Context ctx) { super(ctx); } - public interface OnKeyEventListener - { - boolean onKey(KeyEvent event); - } - + /** + * Interface which defines a callback method for general + * motion events. This allows motion event code to be set + * in the event anonymous classes of this dialog are used. + */ public interface OnMotionEventListener { boolean onMotion(MotionEvent event); } - public void setOnKeyEventListener(OnKeyEventListener listener) - { - this.keyListener = listener; - } - + /** + * Sets the motion listener. + * + * @param listener The motion listener to set. + */ public void setOnMotionEventListener(OnMotionEventListener listener) { this.motionListener = listener; } - + @Override public boolean dispatchKeyEvent(KeyEvent event) { - if (keyListener.onKey(event)) + if (this.onKeyDown(event.getKeyCode(), event)) return true; return super.dispatchKeyEvent(event); From d83dffe44284163f87e48fe335296e7afde9a6cb Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Mon, 26 Aug 2013 12:19:24 -0500 Subject: [PATCH 12/17] [Android] Add wad file support. --- .../dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java | 2 +- .../org/dolphinemu/dolphinemu/gamelist/GameListFragment.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 56fe57cb2e..4733cc18da 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -54,7 +54,7 @@ public final class FolderBrowser extends Fragment Listfls = new ArrayList(); // Supported extensions to filter by - Set validExts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff")); + Set validExts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff", ".wad")); // Search for any directories or files within the current dir. for(File entry : dirs) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 6d4a4bfe22..9c254f7b9d 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -69,7 +69,7 @@ public final class GameListFragment extends Fragment int intDirectories = Integer.parseInt(Directories); // Extensions to filter by. - Set exts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff")); + Set exts = new HashSet(Arrays.asList(".gcm", ".iso", ".wbfs", ".gcz", ".dol", ".elf", ".dff", ".wad")); for (int a = 0; a < intDirectories; ++a) { @@ -159,4 +159,4 @@ public final class GameListFragment extends Fragment + " must implement OnGameListZeroListener"); } } -} \ No newline at end of file +} From 15df7b3445f54cfcbe303aded3a7d1ec33fa4776 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 26 Aug 2013 19:45:19 +0200 Subject: [PATCH 13/17] ogl driverdetails: add flag to disable hacked and pinned memory pinned memory is broken for index buffers hacked buffer crashes the amd driver --- Source/Core/VideoCommon/Src/DriverDetails.cpp | 15 +++++++++------ Source/Core/VideoCommon/Src/DriverDetails.h | 16 ++++++++++++++++ .../Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp | 5 +++-- .../Plugin_VideoOGL/Src/VertexManager.cpp | 5 +---- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 0a115e1354..cdecc71cd1 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -27,12 +27,15 @@ namespace DriverDetails // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, - {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, - {VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, - {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, + {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENUBO, 900, 916, true}, + {VENDOR_MESA, DRIVER_R600, BUG_BROKENUBO, 900, 913, true}, + {VENDOR_MESA, DRIVER_I965, BUG_BROKENUBO, 900, 920, true}, + {VENDOR_ATI, DRIVER_ATI, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {VENDOR_MESA, DRIVER_NOUVEAU, BUG_BROKENHACKEDBUFFER, -1.0, -1.0, true}, + {VENDOR_ATI, DRIVER_ATI, BUG_BROKENPINNEDMEMORY, -1.0, -1.0, true} }; std::map m_bugs; diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index efb0c7c6c0..dc0d2900eb 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -83,6 +83,22 @@ namespace DriverDetails // Nouveau stored the offset as u16 which isn't enough for all cases with range until 9.1.6 // I965 has broken data fetches from uniform buffers which results in a dithering until 9.2.0 BUG_BROKENUBO, + // Bug: The hacked buffer upload method isn't working + // This isn't a bug as the hacked buffer itself isn't used to work. + // I'm still surprised that it works on so many drivers. + // Affected devices: - amd close sourced driver + // - nouveau + // - maybe also some others + // This hack is evil. It's like free(pointer); *pointer = data; + BUG_BROKENHACKEDBUFFER, + // Bug: The pinned memory extension isn't working for index buffers + // Affected devices: AMD as they are the only vendor providing this extension + // Started Version: ? + // Ended Version: -1 + // Pinned memory is disabled for index buffer as the amd driver (the only one with pinned memory support) seems + // to be broken. We just get flickering/black rendering when using pinned memory here -- degasus - 2013/08/20 + // Please see issue #6105 on google code. Let's hope buffer storage solves this issues. + BUG_BROKENPINNEDMEMORY, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp index af013467eb..e03bcfbef4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp @@ -7,6 +7,7 @@ #include "StreamBuffer.h" #include "MemoryUtil.h" #include "Render.h" +#include "DriverDetails.h" namespace OGL { @@ -27,9 +28,9 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType) m_uploadtype = BUFFERDATA; else if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; - else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) + else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && !DriverDetails::HasBug(DriverDetails::BUG_BROKENHACKEDBUFFER) && (m_uploadtype & MAP_AND_RISK)) m_uploadtype = MAP_AND_RISK; - else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (m_uploadtype & PINNED_MEMORY)) + else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) || type != GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY)) m_uploadtype = PINNED_MEMORY; else if(nvidia && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 8dc884ea63..3f4547a005 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -62,10 +62,7 @@ void VertexManager::CreateDeviceObjects() s_vertexBuffer = new StreamBuffer(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE); m_vertex_buffers = s_vertexBuffer->getBuffer(); - // Pinned memory is disabled for index buffer as the amd driver (the only one with pinned memory support) seems - // to be broken. We just get flickering/black rendering when using pinned memory here -- degasus - 2013/08/20 - // Please see issue #6105 on google code. Let's hope buffer storage solves this issues. - s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE, (StreamType)(DETECT_MASK & ~PINNED_MEMORY)); + s_indexBuffer = new StreamBuffer(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE); m_index_buffers = s_indexBuffer->getBuffer(); m_CurrentVertexFmt = NULL; From 93f9f235769cbf37a4f701efeea8dbf92f7c339e Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 26 Aug 2013 22:18:00 +0200 Subject: [PATCH 14/17] ogl: reset api state for blitting glBlitFramebuffer depends on scissior test and color mask. It isn't documented well, but it does. So we have to reset the apistate before using it. In this way, there isn't any benefit of glBlitFramebuffer, glDrawArray would be better :-( --- Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp | 4 ++++ Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp index ceafb75dca..eeea9da38b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp @@ -435,6 +435,8 @@ void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) void XFBSource::CopyEFB(float Gamma) { + g_renderer->ResetAPIState(); + // Copy EFB data to XFB and restore render target again glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetEFBFramebuffer()); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer()); @@ -451,6 +453,8 @@ void XFBSource::CopyEFB(float Gamma) // Return to EFB. FramebufferManager::SetFramebuffer(0); + + g_renderer->RestoreAPIState(); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index ee159929d1..8ac9fc9d4c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -958,9 +958,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { if (s_MSAASamples > 1) { + g_renderer->ResetAPIState(); + // Resolve our rectangle. FramebufferManager::GetEFBDepthTexture(efbPixelRc); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer()); + + g_renderer->RestoreAPIState(); } u32* depthMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; @@ -1007,9 +1011,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) { if (s_MSAASamples > 1) { + g_renderer->ResetAPIState(); + // Resolve our rectangle. FramebufferManager::GetEFBColorTexture(efbPixelRc); glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetResolvedFramebuffer()); + + g_renderer->RestoreAPIState(); } u32* colorMap = new u32[targetPixelRcWidth * targetPixelRcHeight]; From 76f20cca5912b9761bf3cc484295847dfd8a7e1c Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 27 Aug 2013 04:01:20 -0400 Subject: [PATCH 15/17] [Android] Remove the documentation of a parameter in GameListItem that was removed a while ago. --- .../src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java index 9ecff70b9b..5e5b71da67 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListItem.java @@ -34,7 +34,6 @@ public final class GameListItem implements Comparable * @param name The name of this GameListItem. * @param data The subtitle for this GameListItem * @param path The file path for the game represented by this GameListItem. - * @param isValid Whether or not the emulator can handle this file. */ public GameListItem(Context ctx, String name, String data, String path) { From 4a863c88b43cc1968c54f3c7ebcfbeceec38bf91 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 27 Aug 2013 04:06:18 -0400 Subject: [PATCH 16/17] [Android] Simplify onAttach for CPUSettingsFragment and VideoSettingsFragment --- .../dolphinemu/settings/CPUSettingsFragment.java | 12 ++---------- .../dolphinemu/settings/VideoSettingsFragment.java | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java index e77725087e..e93cbce384 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/CPUSettingsFragment.java @@ -57,16 +57,8 @@ public final class CPUSettingsFragment extends PreferenceFragment { 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()); - } + // Cache the activity instance. + m_activity = activity; } @Override diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java index 3d97f2cbca..b8e82f4dd0 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java @@ -202,16 +202,8 @@ public final class VideoSettingsFragment extends PreferenceFragment { 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()); - } + // Cache the activity instance. + m_activity = activity; } @Override From 40a1cb5dfed6d5b255d1f330af2cdc14446e0b53 Mon Sep 17 00:00:00 2001 From: degasus Date: Tue, 27 Aug 2013 13:24:23 +0200 Subject: [PATCH 17/17] ogl: warn on osd if not supported features are enabled --- .../Plugin_VideoOGL/Src/FramebufferManager.cpp | 8 ++++++++ Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 9 ++++++--- Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp | 11 ++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp index eeea9da38b..f3b8578b23 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "FramebufferManager.h" #include "VertexShaderGen.h" +#include "OnScreenDisplay.h" #include "TextureConverter.h" #include "Render.h" @@ -366,6 +367,13 @@ void FramebufferManager::ReinterpretPixelData(unsigned int convtype) { if(g_ogl_config.eSupportedGLSLVersion == GLSL_120) { // This feature isn't supported by glsl120 + + // TODO: move this to InitBackendInfo + // We have to disable both the active and the stored config. Else we would either + // show this line per format change in one frame or once per frame. + OSD::AddMessage("Format Change Emulation isn't supported by your GPU.", 10000); + g_ActiveConfig.bEFBEmulateFormatChanges = false; + g_Config.bEFBEmulateFormatChanges = false; return; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 8ac9fc9d4c..504e58f85b 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -173,7 +173,8 @@ int GetNumMSAASamples(int MSAAMode) if(samples <= g_ogl_config.max_samples) return samples; - ERROR_LOG(VIDEO, "MSAA Bug: %d samples selected, but only %d supported by GPU.", samples, g_ogl_config.max_samples); + // TODO: move this to InitBackendInfo + OSD::AddMessage(StringFromFormat("%d Anti Aliasing samples selected, but only %d supported by your GPU.", samples, g_ogl_config.max_samples), 10000); return g_ogl_config.max_samples; } @@ -197,7 +198,8 @@ int GetNumMSAACoverageSamples(int MSAAMode) } if(g_ogl_config.bSupportCoverageMSAA || samples == 0) return samples; - ERROR_LOG(VIDEO, "MSAA Bug: CSAA selected, but not supported by GPU."); + // TODO: move this to InitBackendInfo + OSD::AddMessage("CSAA Anti Aliasing isn't supported by your GPU.", 10000); return 0; } @@ -209,7 +211,8 @@ void ApplySSAASettings() { glEnable(GL_SAMPLE_SHADING_ARB); glMinSampleShadingARB(s_MSAASamples); } else { - ERROR_LOG(VIDEO, "MSAA Bug: SSAA selected, but not supported by GPU."); + // TODO: move this to InitBackendInfo + OSD::AddMessage("SSAA Anti Aliasing isn't supported by your GPU.", 10000); } } else if(g_ogl_config.bSupportSampleShading) { glDisable(GL_SAMPLE_SHADING_ARB); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp index e03bcfbef4..5832a292ed 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp @@ -8,6 +8,7 @@ #include "MemoryUtil.h" #include "Render.h" #include "DriverDetails.h" +#include "OnScreenDisplay.h" namespace OGL { @@ -24,11 +25,19 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType) if(m_uploadtype & STREAM_DETECT) { + // TODO: move this to InitBackendInfo + if(g_ActiveConfig.bHackedBufferUpload && !DriverDetails::HasBug(DriverDetails::BUG_BROKENHACKEDBUFFER)) + { + OSD::AddMessage("Vertex Streaming Hack isn't supported by your GPU.", 10000); + g_ActiveConfig.bHackedBufferUpload = false; + g_Config.bHackedBufferUpload = false; + } + if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERDATA)) m_uploadtype = BUFFERDATA; else if(!g_ogl_config.bSupportsGLBaseVertex && (m_uploadtype & BUFFERSUBDATA)) m_uploadtype = BUFFERSUBDATA; - else if(g_ogl_config.bSupportsGLSync && g_Config.bHackedBufferUpload && !DriverDetails::HasBug(DriverDetails::BUG_BROKENHACKEDBUFFER) && (m_uploadtype & MAP_AND_RISK)) + else if(g_ogl_config.bSupportsGLSync && g_ActiveConfig.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK)) m_uploadtype = MAP_AND_RISK; else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) || type != GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY)) m_uploadtype = PINNED_MEMORY;