diff options
Diffstat (limited to 'src/android/app')
9 files changed, 251 insertions, 3 deletions
diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml index 88e1669cd..de4dbb948 100644 --- a/src/android/app/src/main/AndroidManifest.xml +++ b/src/android/app/src/main/AndroidManifest.xml | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | android:supportsRtl="true" | 27 | android:supportsRtl="true" |
| 28 | android:isGame="true" | 28 | android:isGame="true" |
| 29 | android:banner="@mipmap/ic_launcher" | 29 | android:banner="@mipmap/ic_launcher" |
| 30 | android:extractNativeLibs="true" | ||
| 30 | android:requestLegacyExternalStorage="true"> | 31 | android:requestLegacyExternalStorage="true"> |
| 31 | 32 | ||
| 32 | <activity | 33 | <activity |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java index e56196310..c09b711fd 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java | |||
| @@ -181,7 +181,7 @@ public final class NativeLibrary { | |||
| 181 | 181 | ||
| 182 | public static native void SetAppDirectory(String directory); | 182 | public static native void SetAppDirectory(String directory); |
| 183 | 183 | ||
| 184 | public static native void SetGpuDriverParameters(String hookLibDir, String customDriverDir, String customDriverName, String fileRedirectDir); | 184 | public static native void InitializeGpuDriver(String hookLibDir, String customDriverDir, String customDriverName, String fileRedirectDir); |
| 185 | 185 | ||
| 186 | public static native boolean ReloadKeys(); | 186 | public static native boolean ReloadKeys(); |
| 187 | 187 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.java index 9d4ed80b4..830d0b18c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.java | |||
| @@ -13,6 +13,7 @@ import android.os.Build; | |||
| 13 | import org.yuzu.yuzu_emu.model.GameDatabase; | 13 | import org.yuzu.yuzu_emu.model.GameDatabase; |
| 14 | import org.yuzu.yuzu_emu.utils.DocumentsTree; | 14 | import org.yuzu.yuzu_emu.utils.DocumentsTree; |
| 15 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization; | 15 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization; |
| 16 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper; | ||
| 16 | 17 | ||
| 17 | public class YuzuApplication extends Application { | 18 | public class YuzuApplication extends Application { |
| 18 | public static GameDatabase databaseHelper; | 19 | public static GameDatabase databaseHelper; |
| @@ -43,7 +44,7 @@ public class YuzuApplication extends Application { | |||
| 43 | documentsTree = new DocumentsTree(); | 44 | documentsTree = new DocumentsTree(); |
| 44 | 45 | ||
| 45 | DirectoryInitialization.start(getApplicationContext()); | 46 | DirectoryInitialization.start(getApplicationContext()); |
| 46 | 47 | GpuDriverHelper.initializeDriverParameters(getApplicationContext()); | |
| 47 | NativeLibrary.LogDeviceInfo(); | 48 | NativeLibrary.LogDeviceInfo(); |
| 48 | 49 | ||
| 49 | // TODO(bunnei): Disable notifications until we support app suspension. | 50 | // TODO(bunnei): Disable notifications until we support app suspension. |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java index 552232bd3..d5009bc60 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.java | |||
| @@ -9,6 +9,7 @@ import android.view.MenuItem; | |||
| 9 | import android.widget.Toast; | 9 | import android.widget.Toast; |
| 10 | 10 | ||
| 11 | import androidx.annotation.NonNull; | 11 | import androidx.annotation.NonNull; |
| 12 | import androidx.appcompat.app.AlertDialog; | ||
| 12 | import androidx.appcompat.app.AppCompatActivity; | 13 | import androidx.appcompat.app.AppCompatActivity; |
| 13 | import androidx.appcompat.widget.Toolbar; | 14 | import androidx.appcompat.widget.Toolbar; |
| 14 | 15 | ||
| @@ -22,6 +23,7 @@ import org.yuzu.yuzu_emu.utils.AddDirectoryHelper; | |||
| 22 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization; | 23 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization; |
| 23 | import org.yuzu.yuzu_emu.utils.FileBrowserHelper; | 24 | import org.yuzu.yuzu_emu.utils.FileBrowserHelper; |
| 24 | import org.yuzu.yuzu_emu.utils.FileUtil; | 25 | import org.yuzu.yuzu_emu.utils.FileUtil; |
| 26 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper; | ||
| 25 | import org.yuzu.yuzu_emu.utils.PicassoUtils; | 27 | import org.yuzu.yuzu_emu.utils.PicassoUtils; |
| 26 | import org.yuzu.yuzu_emu.utils.StartupHandler; | 28 | import org.yuzu.yuzu_emu.utils.StartupHandler; |
| 27 | import org.yuzu.yuzu_emu.utils.ThemeUtil; | 29 | import org.yuzu.yuzu_emu.utils.ThemeUtil; |
| @@ -128,6 +130,41 @@ public final class MainActivity extends AppCompatActivity implements MainView { | |||
| 128 | MainPresenter.REQUEST_INSTALL_KEYS, | 130 | MainPresenter.REQUEST_INSTALL_KEYS, |
| 129 | R.string.install_keys); | 131 | R.string.install_keys); |
| 130 | break; | 132 | break; |
| 133 | case MainPresenter.REQUEST_SELECT_GPU_DRIVER: | ||
| 134 | AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||
| 135 | |||
| 136 | // Get the driver name for the dialog message. | ||
| 137 | String driverName = GpuDriverHelper.getCustomDriverName(); | ||
| 138 | if (driverName == null) { | ||
| 139 | driverName = getString(R.string.system_gpu_driver); | ||
| 140 | } | ||
| 141 | |||
| 142 | // Set the dialog message and title. | ||
| 143 | builder.setTitle(getString(R.string.select_gpu_driver_title)); | ||
| 144 | builder.setMessage(driverName); | ||
| 145 | |||
| 146 | // Cancel button is a no-op. | ||
| 147 | builder.setNegativeButton(android.R.string.cancel, null); | ||
| 148 | |||
| 149 | // Select the default system driver. | ||
| 150 | builder.setPositiveButton(R.string.select_gpu_driver_default, (dialogInterface, i) -> | ||
| 151 | { | ||
| 152 | GpuDriverHelper.installDefaultDriver(this); | ||
| 153 | Toast.makeText(this, R.string.select_gpu_driver_use_default, Toast.LENGTH_SHORT).show(); | ||
| 154 | }); | ||
| 155 | |||
| 156 | // Use the file picker to install a custom driver. | ||
| 157 | builder.setNeutralButton(R.string.select_gpu_driver_install, (dialogInterface, i) -> { | ||
| 158 | FileBrowserHelper.openFilePicker(this, | ||
| 159 | MainPresenter.REQUEST_SELECT_GPU_DRIVER, | ||
| 160 | R.string.select_gpu_driver); | ||
| 161 | }); | ||
| 162 | |||
| 163 | // Show the dialog. | ||
| 164 | AlertDialog alertDialog = builder.create(); | ||
| 165 | alertDialog.show(); | ||
| 166 | |||
| 167 | break; | ||
| 131 | } | 168 | } |
| 132 | } | 169 | } |
| 133 | 170 | ||
| @@ -163,12 +200,26 @@ public final class MainActivity extends AppCompatActivity implements MainView { | |||
| 163 | Toast.makeText(this, R.string.install_keys_success, Toast.LENGTH_SHORT).show(); | 200 | Toast.makeText(this, R.string.install_keys_success, Toast.LENGTH_SHORT).show(); |
| 164 | refreshFragment(); | 201 | refreshFragment(); |
| 165 | } else { | 202 | } else { |
| 166 | Toast.makeText(this, R.string.install_keys_failure, Toast.LENGTH_SHORT).show(); | 203 | Toast.makeText(this, R.string.install_keys_failure, Toast.LENGTH_LONG).show(); |
| 167 | launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS); | 204 | launchFileListActivity(MainPresenter.REQUEST_INSTALL_KEYS); |
| 168 | } | 205 | } |
| 169 | } | 206 | } |
| 170 | } | 207 | } |
| 171 | break; | 208 | break; |
| 209 | |||
| 210 | case MainPresenter.REQUEST_SELECT_GPU_DRIVER: | ||
| 211 | if (resultCode == MainActivity.RESULT_OK) { | ||
| 212 | int takeFlags = (Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); | ||
| 213 | getContentResolver().takePersistableUriPermission(Uri.parse(result.getDataString()), takeFlags); | ||
| 214 | GpuDriverHelper.installCustomDriver(this, result.getData()); | ||
| 215 | String driverName = GpuDriverHelper.getCustomDriverName(); | ||
| 216 | if (driverName != null) { | ||
| 217 | Toast.makeText(this, getString(R.string.select_gpu_driver_install_success) + " " + driverName, Toast.LENGTH_SHORT).show(); | ||
| 218 | } else { | ||
| 219 | Toast.makeText(this, R.string.select_gpu_driver_error, Toast.LENGTH_LONG).show(); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | break; | ||
| 172 | } | 223 | } |
| 173 | } | 224 | } |
| 174 | 225 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java index 82667a98f..d2ef753bc 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainPresenter.java | |||
| @@ -12,6 +12,7 @@ import org.yuzu.yuzu_emu.utils.AddDirectoryHelper; | |||
| 12 | public final class MainPresenter { | 12 | public final class MainPresenter { |
| 13 | public static final int REQUEST_ADD_DIRECTORY = 1; | 13 | public static final int REQUEST_ADD_DIRECTORY = 1; |
| 14 | public static final int REQUEST_INSTALL_KEYS = 2; | 14 | public static final int REQUEST_INSTALL_KEYS = 2; |
| 15 | public static final int REQUEST_SELECT_GPU_DRIVER = 3; | ||
| 15 | private final MainView mView; | 16 | private final MainView mView; |
| 16 | private String mDirToAdd; | 17 | private String mDirToAdd; |
| 17 | private long mLastClickTime = 0; | 18 | private long mLastClickTime = 0; |
| @@ -51,6 +52,10 @@ public final class MainPresenter { | |||
| 51 | case R.id.button_install_keys: | 52 | case R.id.button_install_keys: |
| 52 | launchFileListActivity(REQUEST_INSTALL_KEYS); | 53 | launchFileListActivity(REQUEST_INSTALL_KEYS); |
| 53 | return true; | 54 | return true; |
| 55 | |||
| 56 | case R.id.button_select_gpu_driver: | ||
| 57 | launchFileListActivity(REQUEST_SELECT_GPU_DRIVER); | ||
| 58 | return true; | ||
| 54 | } | 59 | } |
| 55 | 60 | ||
| 56 | return false; | 61 | return false; |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.java new file mode 100644 index 000000000..822a3f1f9 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.java | |||
| @@ -0,0 +1,130 @@ | |||
| 1 | package org.yuzu.yuzu_emu.utils; | ||
| 2 | |||
| 3 | import android.content.Context; | ||
| 4 | import android.net.Uri; | ||
| 5 | |||
| 6 | import org.yuzu.yuzu_emu.NativeLibrary; | ||
| 7 | |||
| 8 | import java.io.File; | ||
| 9 | import java.io.FileInputStream; | ||
| 10 | import java.io.FileOutputStream; | ||
| 11 | import java.io.IOException; | ||
| 12 | import java.util.zip.ZipEntry; | ||
| 13 | import java.util.zip.ZipInputStream; | ||
| 14 | |||
| 15 | public class GpuDriverHelper { | ||
| 16 | private static final String META_JSON_FILENAME = "meta.json"; | ||
| 17 | private static final String DRIVER_INTERNAL_FILENAME = "gpu_driver.zip"; | ||
| 18 | private static String fileRedirectionPath; | ||
| 19 | private static String driverInstallationPath; | ||
| 20 | private static String hookLibPath; | ||
| 21 | |||
| 22 | private static void unzip(String zipFilePath, String destDir) throws IOException { | ||
| 23 | File dir = new File(destDir); | ||
| 24 | |||
| 25 | // Create output directory if it doesn't exist | ||
| 26 | if (!dir.exists()) dir.mkdirs(); | ||
| 27 | |||
| 28 | // Unpack the files. | ||
| 29 | ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath)); | ||
| 30 | byte[] buffer = new byte[1024]; | ||
| 31 | ZipEntry ze = zis.getNextEntry(); | ||
| 32 | while (ze != null) { | ||
| 33 | String fileName = ze.getName(); | ||
| 34 | File newFile = new File(destDir + fileName); | ||
| 35 | newFile.getParentFile().mkdirs(); | ||
| 36 | FileOutputStream fos = new FileOutputStream(newFile); | ||
| 37 | int len; | ||
| 38 | while ((len = zis.read(buffer)) > 0) { | ||
| 39 | fos.write(buffer, 0, len); | ||
| 40 | } | ||
| 41 | fos.close(); | ||
| 42 | zis.closeEntry(); | ||
| 43 | ze = zis.getNextEntry(); | ||
| 44 | } | ||
| 45 | zis.closeEntry(); | ||
| 46 | } | ||
| 47 | |||
| 48 | public static void initializeDriverParameters(Context context) { | ||
| 49 | try { | ||
| 50 | // Initialize the file redirection directory. | ||
| 51 | fileRedirectionPath = context.getExternalFilesDir(null).getCanonicalPath() + "/gpu/vk_file_redirect/"; | ||
| 52 | |||
| 53 | // Initialize the driver installation directory. | ||
| 54 | driverInstallationPath = context.getFilesDir().getCanonicalPath() + "/gpu_driver/"; | ||
| 55 | } catch (IOException e) { | ||
| 56 | throw new RuntimeException(e); | ||
| 57 | } | ||
| 58 | |||
| 59 | // Initialize directories. | ||
| 60 | initializeDirectories(); | ||
| 61 | |||
| 62 | // Initialize hook libraries directory. | ||
| 63 | hookLibPath = context.getApplicationInfo().nativeLibraryDir + "/"; | ||
| 64 | |||
| 65 | // Initialize GPU driver. | ||
| 66 | NativeLibrary.InitializeGpuDriver(hookLibPath, driverInstallationPath, getCustomDriverLibraryName(), fileRedirectionPath); | ||
| 67 | } | ||
| 68 | |||
| 69 | public static void installDefaultDriver(Context context) { | ||
| 70 | // Removing the installed driver will result in the backend using the default system driver. | ||
| 71 | File driverInstallationDir = new File(driverInstallationPath); | ||
| 72 | deleteRecursive(driverInstallationDir); | ||
| 73 | initializeDriverParameters(context); | ||
| 74 | } | ||
| 75 | |||
| 76 | public static void installCustomDriver(Context context, Uri driverPathUri) { | ||
| 77 | // Revert to system default in the event the specified driver is bad. | ||
| 78 | installDefaultDriver(context); | ||
| 79 | |||
| 80 | // Ensure we have directories. | ||
| 81 | initializeDirectories(); | ||
| 82 | |||
| 83 | // Copy the zip file URI into our private storage. | ||
| 84 | FileUtil.copyUriToInternalStorage(context, driverPathUri, driverInstallationPath, DRIVER_INTERNAL_FILENAME); | ||
| 85 | |||
| 86 | // Unzip the driver. | ||
| 87 | try { | ||
| 88 | unzip(driverInstallationPath + DRIVER_INTERNAL_FILENAME, driverInstallationPath); | ||
| 89 | } catch (IOException e) { | ||
| 90 | throw new RuntimeException(e); | ||
| 91 | } | ||
| 92 | |||
| 93 | // Initialize the driver parameters. | ||
| 94 | initializeDriverParameters(context); | ||
| 95 | } | ||
| 96 | |||
| 97 | public static String getCustomDriverName() { | ||
| 98 | // Parse the custom driver metadata to retrieve the name. | ||
| 99 | GpuDriverMetadata metadata = new GpuDriverMetadata(driverInstallationPath + META_JSON_FILENAME); | ||
| 100 | return metadata.name; | ||
| 101 | } | ||
| 102 | |||
| 103 | private static String getCustomDriverLibraryName() { | ||
| 104 | // Parse the custom driver metadata to retrieve the library name. | ||
| 105 | GpuDriverMetadata metadata = new GpuDriverMetadata(driverInstallationPath + META_JSON_FILENAME); | ||
| 106 | return metadata.libraryName; | ||
| 107 | } | ||
| 108 | |||
| 109 | private static void initializeDirectories() { | ||
| 110 | // Ensure the file redirection directory exists. | ||
| 111 | File fileRedirectionDir = new File(fileRedirectionPath); | ||
| 112 | if (!fileRedirectionDir.exists()) { | ||
| 113 | fileRedirectionDir.mkdirs(); | ||
| 114 | } | ||
| 115 | // Ensure the driver installation directory exists. | ||
| 116 | File driverInstallationDir = new File(driverInstallationPath); | ||
| 117 | if (!driverInstallationDir.exists()) { | ||
| 118 | driverInstallationDir.mkdirs(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | private static void deleteRecursive(File fileOrDirectory) { | ||
| 123 | if (fileOrDirectory.isDirectory()) { | ||
| 124 | for (File child : fileOrDirectory.listFiles()) { | ||
| 125 | deleteRecursive(child); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | fileOrDirectory.delete(); | ||
| 129 | } | ||
| 130 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverMetadata.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverMetadata.java new file mode 100644 index 000000000..d2bb2dd23 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverMetadata.java | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | package org.yuzu.yuzu_emu.utils; | ||
| 2 | |||
| 3 | import org.json.JSONException; | ||
| 4 | import org.json.JSONObject; | ||
| 5 | |||
| 6 | import java.io.IOException; | ||
| 7 | import java.nio.charset.StandardCharsets; | ||
| 8 | import java.nio.file.Files; | ||
| 9 | import java.nio.file.Path; | ||
| 10 | import java.nio.file.Paths; | ||
| 11 | |||
| 12 | public class GpuDriverMetadata { | ||
| 13 | |||
| 14 | public String name; | ||
| 15 | public String description; | ||
| 16 | public String author; | ||
| 17 | public String vendor; | ||
| 18 | public String driverVersion; | ||
| 19 | public int minApi; | ||
| 20 | public String libraryName; | ||
| 21 | |||
| 22 | public GpuDriverMetadata(String metadataFilePath) { | ||
| 23 | try { | ||
| 24 | JSONObject json = new JSONObject(getStringFromFile(metadataFilePath)); | ||
| 25 | name = json.getString("name"); | ||
| 26 | description = json.getString("description"); | ||
| 27 | author = json.getString("author"); | ||
| 28 | vendor = json.getString("vendor"); | ||
| 29 | driverVersion = json.getString("driverVersion"); | ||
| 30 | minApi = json.getInt("minApi"); | ||
| 31 | libraryName = json.getString("libraryName"); | ||
| 32 | } catch (JSONException e) { | ||
| 33 | // JSON is malformed, ignore and treat as unsupported metadata. | ||
| 34 | } catch (IOException e) { | ||
| 35 | // File is inaccessible, ignore and treat as unsupported metadata. | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | private static String getStringFromFile(String filePath) throws IOException { | ||
| 40 | Path path = Paths.get(filePath); | ||
| 41 | byte[] bytes = Files.readAllBytes(path); | ||
| 42 | return new String(bytes, StandardCharsets.UTF_8); | ||
| 43 | } | ||
| 44 | |||
| 45 | } | ||
diff --git a/src/android/app/src/main/res/menu/menu_game_grid.xml b/src/android/app/src/main/res/menu/menu_game_grid.xml index 3eb8cf817..6211f5494 100644 --- a/src/android/app/src/main/res/menu/menu_game_grid.xml +++ b/src/android/app/src/main/res/menu/menu_game_grid.xml | |||
| @@ -18,6 +18,11 @@ | |||
| 18 | android:icon="@drawable/ic_install" | 18 | android:icon="@drawable/ic_install" |
| 19 | android:title="@string/install_keys" | 19 | android:title="@string/install_keys" |
| 20 | app:showAsAction="ifRoom" /> | 20 | app:showAsAction="ifRoom" /> |
| 21 | <item | ||
| 22 | android:id="@+id/button_select_gpu_driver" | ||
| 23 | android:icon="@drawable/ic_settings_core" | ||
| 24 | android:title="@string/select_gpu_driver" | ||
| 25 | app:showAsAction="ifRoom" /> | ||
| 21 | </menu> | 26 | </menu> |
| 22 | </item> | 27 | </item> |
| 23 | <item | 28 | <item |
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index e450ee869..27749b287 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
| @@ -53,6 +53,16 @@ | |||
| 53 | <string name="install_keys_success">Keys successfully installed</string> | 53 | <string name="install_keys_success">Keys successfully installed</string> |
| 54 | <string name="install_keys_failure">Keys file (prod.keys) is invalid</string> | 54 | <string name="install_keys_failure">Keys file (prod.keys) is invalid</string> |
| 55 | 55 | ||
| 56 | <!-- GPU driver installation --> | ||
| 57 | <string name="select_gpu_driver">Select GPU driver</string> | ||
| 58 | <string name="select_gpu_driver_title">Would you like to replace your current GPU driver?</string> | ||
| 59 | <string name="select_gpu_driver_install">Install</string> | ||
| 60 | <string name="select_gpu_driver_default">Default</string> | ||
| 61 | <string name="select_gpu_driver_install_success">Installed</string> | ||
| 62 | <string name="select_gpu_driver_use_default">Using default GPU driver</string> | ||
| 63 | <string name="select_gpu_driver_error">Invalid driver selected, using system default!</string> | ||
| 64 | <string name="system_gpu_driver">System GPU driver</string> | ||
| 65 | |||
| 56 | <!-- Preferences Screen --> | 66 | <!-- Preferences Screen --> |
| 57 | <string name="preferences_settings">Settings</string> | 67 | <string name="preferences_settings">Settings</string> |
| 58 | <string name="preferences_general">General</string> | 68 | <string name="preferences_general">General</string> |