mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
added custom driver option in settings
This commit is contained in:
@@ -805,6 +805,18 @@ static SetupFiles SyncSetupFiles() {
|
||||
int displayMode = GetPrefInt(env, activity, "setting_display_mode", 0);
|
||||
xemu_android_set_display_mode_setting(displayMode);
|
||||
|
||||
const std::string vulkanDriverUri = GetPrefString(env, activity, "setting_vulkan_driver_uri");
|
||||
if (!vulkanDriverUri.empty()) {
|
||||
std::string driverPath = base + "/vulkan_driver.so";
|
||||
if (CopyUriToPath(env, activity, vulkanDriverUri, driverPath)) {
|
||||
chmod(driverPath.c_str(), 0755);
|
||||
setenv("XEMU_VULKAN_DRIVER", driverPath.c_str(), 1);
|
||||
LogInfoFmt("Custom Vulkan driver staged: %s", driverPath.c_str());
|
||||
} else {
|
||||
LogError("Failed to copy custom Vulkan driver; using system default");
|
||||
}
|
||||
}
|
||||
|
||||
out.config_path = base + "/xemu.toml";
|
||||
WriteConfigToml(out.config_path, out.mcpx, out.flash, out.hdd, out.dvd, out.eeprom, emuSettings);
|
||||
LogInfoFmt("SyncSetupFiles: config %s", out.config_path.c_str());
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.izzy2lost.x1box
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.OpenableColumns
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
@@ -12,6 +16,21 @@ class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
private val prefs by lazy { getSharedPreferences("x1box_prefs", Context.MODE_PRIVATE) }
|
||||
|
||||
private var pendingVulkanUri: String? = null
|
||||
private var pendingVulkanName: String? = null
|
||||
private var clearVulkan = false
|
||||
|
||||
private lateinit var tvVulkanDriverName: TextView
|
||||
|
||||
private val pickDriver =
|
||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? ->
|
||||
uri ?: return@registerForActivityResult
|
||||
pendingVulkanUri = uri.toString()
|
||||
pendingVulkanName = getFileName(uri) ?: uri.lastPathSegment ?: "custom_driver.so"
|
||||
clearVulkan = false
|
||||
tvVulkanDriverName.text = pendingVulkanName
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
@@ -30,6 +49,9 @@ class SettingsActivity : AppCompatActivity() {
|
||||
val switchFpu = findViewById<MaterialSwitch>(R.id.switch_hard_fpu)
|
||||
val toggleAudioDriver = findViewById<MaterialButtonToggleGroup>(R.id.toggle_audio_driver)
|
||||
val btnSave = findViewById<MaterialButton>(R.id.btn_settings_save)
|
||||
tvVulkanDriverName = findViewById(R.id.tv_vulkan_driver_name)
|
||||
val btnVulkanBrowse = findViewById<MaterialButton>(R.id.btn_vulkan_browse)
|
||||
val btnVulkanClear = findViewById<MaterialButton>(R.id.btn_vulkan_clear)
|
||||
|
||||
// Load current values
|
||||
val scale = prefs.getInt("setting_surface_scale", 1)
|
||||
@@ -46,6 +68,10 @@ class SettingsActivity : AppCompatActivity() {
|
||||
else -> toggleDisplayMode.check(R.id.btn_display_stretch)
|
||||
}
|
||||
|
||||
tvVulkanDriverName.text =
|
||||
prefs.getString("setting_vulkan_driver_name", null)
|
||||
?: getString(R.string.settings_vulkan_driver_none)
|
||||
|
||||
val tcgThread = prefs.getString("setting_tcg_thread", "multi") ?: "multi"
|
||||
if (tcgThread == "single") {
|
||||
toggleThread.check(R.id.btn_thread_single)
|
||||
@@ -65,6 +91,17 @@ class SettingsActivity : AppCompatActivity() {
|
||||
else -> toggleAudioDriver.check(R.id.btn_audio_opensles)
|
||||
}
|
||||
|
||||
btnVulkanBrowse.setOnClickListener {
|
||||
pickDriver.launch(arrayOf("*/*"))
|
||||
}
|
||||
|
||||
btnVulkanClear.setOnClickListener {
|
||||
pendingVulkanUri = null
|
||||
pendingVulkanName = null
|
||||
clearVulkan = true
|
||||
tvVulkanDriverName.text = getString(R.string.settings_vulkan_driver_none)
|
||||
}
|
||||
|
||||
btnSave.setOnClickListener {
|
||||
val selectedDisplayMode = when (toggleDisplayMode.checkedButtonId) {
|
||||
R.id.btn_display_4_3 -> 1
|
||||
@@ -86,7 +123,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
else -> "openslES"
|
||||
}
|
||||
|
||||
prefs.edit()
|
||||
val edit = prefs.edit()
|
||||
.putInt("setting_display_mode", selectedDisplayMode)
|
||||
.putInt("setting_surface_scale", selectedScale)
|
||||
.putString("setting_tcg_thread", selectedThread)
|
||||
@@ -95,10 +132,27 @@ class SettingsActivity : AppCompatActivity() {
|
||||
.putBoolean("setting_cache_shaders", switchShaders.isChecked)
|
||||
.putBoolean("setting_hard_fpu", switchFpu.isChecked)
|
||||
.putString("setting_audio_driver", selectedAudioDriver)
|
||||
.apply()
|
||||
|
||||
when {
|
||||
clearVulkan -> edit
|
||||
.remove("setting_vulkan_driver_uri")
|
||||
.remove("setting_vulkan_driver_name")
|
||||
pendingVulkanUri != null -> edit
|
||||
.putString("setting_vulkan_driver_uri", pendingVulkanUri)
|
||||
.putString("setting_vulkan_driver_name", pendingVulkanName)
|
||||
}
|
||||
|
||||
edit.apply()
|
||||
|
||||
Toast.makeText(this, R.string.settings_saved, Toast.LENGTH_SHORT).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFileName(uri: Uri): String? {
|
||||
return contentResolver.query(uri, null, null, null, null)?.use { cursor ->
|
||||
val col = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
||||
if (col >= 0 && cursor.moveToFirst()) cursor.getString(col) else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,59 @@
|
||||
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<!-- ── VULKAN DRIVER ── -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/settings_section_vulkan_driver"
|
||||
android:textAppearance="@style/TextAppearance.Material3.LabelLarge"
|
||||
android:textColor="@color/xemu_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_vulkan_driver_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_vulkan_browse"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_vulkan_driver_browse" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_vulkan_clear"
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/settings_vulkan_driver_clear" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/settings_vulkan_driver_hint"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
|
||||
android:textColor="@color/xemu_text_muted" />
|
||||
|
||||
<!-- ── PERFORMANCE ── -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -80,6 +80,11 @@
|
||||
<string name="settings_save">Save</string>
|
||||
|
||||
<string name="settings_section_display">Display</string>
|
||||
<string name="settings_section_vulkan_driver">Custom Vulkan Driver</string>
|
||||
<string name="settings_vulkan_driver_none">System Default</string>
|
||||
<string name="settings_vulkan_driver_browse">Browse…</string>
|
||||
<string name="settings_vulkan_driver_clear">Clear</string>
|
||||
<string name="settings_vulkan_driver_hint">For Adreno GPUs with Turnip/Mesa. Restart required.</string>
|
||||
<string name="settings_display_mode">Aspect Ratio</string>
|
||||
<string name="settings_display_mode_stretch">Stretch</string>
|
||||
<string name="settings_display_mode_4_3">4:3</string>
|
||||
|
||||
@@ -24,9 +24,38 @@
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#include <volk.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static void *g_custom_vk_handle = NULL;
|
||||
|
||||
static bool android_try_load_custom_vulkan(void)
|
||||
{
|
||||
const char *path = getenv("XEMU_VULKAN_DRIVER");
|
||||
if (!path || path[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
g_custom_vk_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||
if (!g_custom_vk_handle) {
|
||||
fprintf(stderr, "Custom Vulkan driver dlopen failed: %s\n", dlerror());
|
||||
return false;
|
||||
}
|
||||
PFN_vkGetInstanceProcAddr proc =
|
||||
(PFN_vkGetInstanceProcAddr)dlsym(g_custom_vk_handle, "vkGetInstanceProcAddr");
|
||||
if (!proc) {
|
||||
fprintf(stderr, "Custom Vulkan driver: vkGetInstanceProcAddr not found\n");
|
||||
dlclose(g_custom_vk_handle);
|
||||
g_custom_vk_handle = NULL;
|
||||
return false;
|
||||
}
|
||||
volkInitializeCustom(proc);
|
||||
fprintf(stderr, "Custom Vulkan driver loaded: %s\n", path);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VkExtensionPropertiesArray GArray
|
||||
#define StringArray GArray
|
||||
|
||||
@@ -154,7 +183,15 @@ static bool create_instance(PGRAPHState *pg, Error **errp)
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
VkResult result;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (!android_try_load_custom_vulkan()) {
|
||||
result = volkInitialize();
|
||||
} else {
|
||||
result = VK_SUCCESS;
|
||||
}
|
||||
#else
|
||||
result = volkInitialize();
|
||||
#endif
|
||||
if (result != VK_SUCCESS) {
|
||||
error_setg(errp, "volkInitialize failed");
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user