* @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)
{
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/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/InputConfigFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java
new file mode 100644
index 0000000000..8914c496b9
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/InputConfigFragment.java
@@ -0,0 +1,264 @@
+/**
+ * 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();
+
+ /**
+ * 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.
+ final MotionAlertDialog dialog = new MotionAlertDialog(m_activity);
+
+ // Set the key listener
+ dialog.setOnKeyListener(new AlertDialog.OnKeyListener()
+ {
+ public boolean onKey(DialogInterface dlg, int keyCode, 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);
+ 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();
+ }
+ }
+ }
+
+ 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 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
+ {
+ private OnMotionEventListener motionListener;
+
+ /**
+ * Constructor
+ *
+ * @param ctx context to use this dialog in.
+ */
+ public MotionAlertDialog(Context ctx)
+ {
+ super(ctx);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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 (this.onKeyDown(event.getKeyCode(), event))
+ return true;
+
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean dispatchGenericMotionEvent(MotionEvent 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 08685fa008..dc75de2550 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/PrefsActivity.java
@@ -72,6 +72,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));
}
@@ -111,6 +112,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 +126,7 @@ public final class PrefsActivity extends Activity implements ActionBar.TabListen
public int getCount()
{
// Show total pages.
- return 2;
+ return 3;
}
@Override
@@ -134,6 +138,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.
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
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/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/FramebufferManager.cpp
index ceafb75dca..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;
}
@@ -435,6 +443,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 +461,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..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);
@@ -958,9 +961,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 +1014,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];
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
index af013467eb..5832a292ed 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/StreamBuffer.cpp
@@ -7,6 +7,8 @@
#include "StreamBuffer.h"
#include "MemoryUtil.h"
#include "Render.h"
+#include "DriverDetails.h"
+#include "OnScreenDisplay.h"
namespace OGL
{
@@ -23,13 +25,21 @@ 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 && (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 && (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;