mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
fix small window in bottom left bug. Mali Mediatek fixes
This commit is contained in:
@@ -201,14 +201,9 @@ static std::string ToLowerAscii(std::string value) {
|
||||
static std::string ResolveAndroidAudioDriverHint() {
|
||||
// OpenSL ES is preferred over AAudio because AAudio exclusively requests
|
||||
// MMAP no-IRQ low-latency outputs (AUDIO_OUTPUT_FLAG_MMAP_NOIRQ). On some
|
||||
// devices (e.g. Honor/Huawei with Android 14+, Snapdragon 8 Gen 3/Adreno 840)
|
||||
// the MMAP output count is capped and openDirectOutput fails when the limit
|
||||
// is reached, leaving the audio stream permanently inactive (isActive:0) and
|
||||
// hanging the audio thread with 1ms timeouts in AudioStreamInternal_Client.
|
||||
// AAudio is deliberately excluded from the default chain: if OpenSL ES fails
|
||||
// for any reason, "android" (standard AudioTrack) is the next safe fallback.
|
||||
// "dummy" is the silent no-op driver used as a last resort so that audio
|
||||
// failure never prevents the emulator from starting.
|
||||
// devices the MMAP output count is capped and openDirectOutput fails when
|
||||
// the limit is reached, leaving the audio stream inactive. The standard
|
||||
// Android AudioTrack backend remains the safe fallback.
|
||||
constexpr const char* kDefaultAudioDriverHint = "openslES,android,dummy";
|
||||
const char* value = SDL_getenv("XEMU_ANDROID_AUDIO_DRIVER");
|
||||
if (!value || value[0] == '\0') {
|
||||
@@ -227,7 +222,10 @@ static std::string ResolveAndroidAudioDriverHint() {
|
||||
return "aaudio,android,dummy";
|
||||
}
|
||||
if (normalized == "android" || normalized == "audiotrack") {
|
||||
return "android,dummy";
|
||||
// Legacy recovery: a saved "android" preference should no longer force
|
||||
// AudioTrack first, because that path was found to exit immediately on
|
||||
// some devices. Fall back to the old OpenSL ES-first behavior.
|
||||
return "openslES,android,dummy";
|
||||
}
|
||||
if (normalized == "null" || normalized == "none" || normalized == "dummy") {
|
||||
return "dummy";
|
||||
@@ -723,7 +721,7 @@ struct EmulatorSettings {
|
||||
bool hrtf = true;
|
||||
bool cache_shaders = true;
|
||||
bool hard_fpu = true;
|
||||
bool vsync = false;
|
||||
bool vsync = true;
|
||||
bool skip_boot_anim = false;
|
||||
};
|
||||
|
||||
@@ -983,8 +981,14 @@ static SetupFiles SyncSetupFiles() {
|
||||
emuSettings.filtering = "nearest";
|
||||
}
|
||||
}
|
||||
emuSettings.vsync = GetPrefBool(env, activity, "setting_vsync", false);
|
||||
emuSettings.vsync = GetPrefBool(env, activity, "setting_vsync", true);
|
||||
out.audio_driver = GetPrefString(env, activity, "setting_audio_driver");
|
||||
{
|
||||
std::string normalized = ToLowerAscii(out.audio_driver);
|
||||
if (normalized == "android" || normalized == "audiotrack") {
|
||||
out.audio_driver = "openslES";
|
||||
}
|
||||
}
|
||||
|
||||
int displayMode = GetPrefInt(env, activity, "setting_display_mode", 0);
|
||||
xemu_android_set_display_mode_setting(displayMode);
|
||||
|
||||
@@ -76,7 +76,7 @@ static void xemu_settings_apply_defaults(void)
|
||||
CONFIG_DISPLAY_WINDOW_STARTUP_SIZE_1280X960;
|
||||
g_config.display.window.last_width = 640;
|
||||
g_config.display.window.last_height = 480;
|
||||
g_config.display.window.vsync = false;
|
||||
g_config.display.window.vsync = true;
|
||||
g_config.display.ui.show_menubar = true;
|
||||
g_config.display.ui.show_notifications = true;
|
||||
g_config.display.ui.hide_cursor = true;
|
||||
@@ -392,8 +392,8 @@ bool xemu_settings_load(void)
|
||||
if (auto audio_driver = android_cfg["audio_driver"].value<std::string>()) {
|
||||
std::string driver = *audio_driver;
|
||||
std::string normalized = to_lower_ascii(driver);
|
||||
if (normalized == "audiotrack") {
|
||||
setenv("XEMU_ANDROID_AUDIO_DRIVER", "android", 1);
|
||||
if (normalized == "audiotrack" || normalized == "android") {
|
||||
setenv("XEMU_ANDROID_AUDIO_DRIVER", "opensles", 1);
|
||||
} else if (normalized == "opensl" || normalized == "opensles") {
|
||||
setenv("XEMU_ANDROID_AUDIO_DRIVER", "opensles", 1);
|
||||
} else if (normalized == "auto" || normalized == "default") {
|
||||
|
||||
@@ -7,12 +7,14 @@ import android.hardware.input.InputManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.InputDevice
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsController
|
||||
import android.view.WindowManager
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
@@ -33,6 +35,7 @@ class MainActivity : SDLActivity(), InputManager.InputDeviceListener {
|
||||
const val EXTRA_AUTO_LOAD_SNAPSHOT_SLOT = "com.izzy2lost.x1box.extra.AUTO_LOAD_SNAPSHOT_SLOT"
|
||||
private const val SNAPSHOT_PREVIEW_HEADER_SIZE = 12
|
||||
private const val TOTAL_SNAPSHOT_SLOTS = 10
|
||||
private const val TAG = "MainActivity"
|
||||
}
|
||||
|
||||
private data class SnapshotSlotPreview(
|
||||
@@ -60,11 +63,13 @@ class MainActivity : SDLActivity(), InputManager.InputDeviceListener {
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
keepScreenOn = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
val requestedSlot = intent?.getIntExtra(EXTRA_AUTO_LOAD_SNAPSHOT_SLOT, 0) ?: 0
|
||||
if (requestedSlot in 1..TOTAL_SNAPSHOT_SLOTS) {
|
||||
startupSnapshotSlot = requestedSlot
|
||||
@@ -155,6 +160,8 @@ class MainActivity : SDLActivity(), InputManager.InputDeviceListener {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
mLayout?.keepScreenOn = true
|
||||
|
||||
// Register virtual controller after SDL is initialized
|
||||
// Use a delay to ensure SDL is fully ready
|
||||
@@ -272,6 +279,7 @@ class MainActivity : SDLActivity(), InputManager.InputDeviceListener {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "onDestroy()")
|
||||
inGameMenuDialog?.dismiss()
|
||||
inGameMenuDialog = null
|
||||
|
||||
@@ -283,9 +291,25 @@ class MainActivity : SDLActivity(), InputManager.InputDeviceListener {
|
||||
}
|
||||
|
||||
inputManager?.unregisterInputDeviceListener(this)
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
Log.i(TAG, "onUserLeaveHint()")
|
||||
super.onUserLeaveHint()
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
Log.i(TAG, "onTrimMemory(level=$level)")
|
||||
super.onTrimMemory(level)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
Log.w(TAG, "onLowMemory()")
|
||||
super.onLowMemory()
|
||||
}
|
||||
|
||||
// Manual control methods (for settings/preferences)
|
||||
fun toggleOnScreenController() {
|
||||
isControllerVisible = !isControllerVisible
|
||||
|
||||
@@ -166,7 +166,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
switchHrtf.isChecked = prefs.getBoolean("setting_hrtf", true)
|
||||
switchShaders.isChecked = prefs.getBoolean("setting_cache_shaders", true)
|
||||
switchFpu.isChecked = prefs.getBoolean("setting_hard_fpu", true)
|
||||
switchVsync.isChecked = prefs.getBoolean("setting_vsync", false)
|
||||
switchVsync.isChecked = prefs.getBoolean("setting_vsync", true)
|
||||
switchSkipBootAnim.isChecked =
|
||||
prefs.getBoolean("setting_skip_boot_anim", false)
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ MString *pgraph_glsl_gen_geom(const GeomState *state, GenGeomGlslOptions opts)
|
||||
|
||||
bool need_triz = false;
|
||||
bool need_linez = false;
|
||||
bool need_point_size = false;
|
||||
const char *layout_in = NULL;
|
||||
const char *layout_out = NULL;
|
||||
const char *body = NULL;
|
||||
@@ -99,6 +100,7 @@ MString *pgraph_glsl_gen_geom(const GeomState *state, GenGeomGlslOptions opts)
|
||||
" emit_line(2, 0, dz);\n";
|
||||
} else {
|
||||
assert(polygon_mode == POLY_MODE_POINT);
|
||||
need_point_size = true;
|
||||
layout_out = "layout(points, max_vertices = 3) out;\n";
|
||||
body = " mat4 pz = calc_triz(0, 1, 2);\n"
|
||||
" emit_vertex(0, mat4(pz[0], pz[0], pz[0], pz[3]));\n"
|
||||
@@ -134,11 +136,14 @@ MString *pgraph_glsl_gen_geom(const GeomState *state, GenGeomGlslOptions opts)
|
||||
|
||||
const char *point_size_expr =
|
||||
opts.gles ? "v_vtxPointSize[index]" : "gl_in[index].gl_PointSize";
|
||||
mstring_append(output,
|
||||
"void emit_vertex(int index, mat4 pz) {\n"
|
||||
" gl_Position = gl_in[index].gl_Position;\n");
|
||||
if (need_point_size) {
|
||||
mstring_append_fmt(output, " gl_PointSize = %s;\n", point_size_expr);
|
||||
}
|
||||
mstring_append_fmt(
|
||||
output,
|
||||
"void emit_vertex(int index, mat4 pz) {\n"
|
||||
" gl_Position = gl_in[index].gl_Position;\n"
|
||||
" gl_PointSize = %s;\n"
|
||||
" vtxD0 = v_vtxD0[%s];\n"
|
||||
" vtxD1 = v_vtxD1[%s];\n"
|
||||
" vtxB0 = v_vtxB0[%s];\n"
|
||||
@@ -155,7 +160,6 @@ MString *pgraph_glsl_gen_geom(const GeomState *state, GenGeomGlslOptions opts)
|
||||
" vtxPointSize = v_vtxPointSize[index];\n"
|
||||
" EmitVertex();\n"
|
||||
"}\n",
|
||||
point_size_expr,
|
||||
provoking_index,
|
||||
provoking_index,
|
||||
provoking_index,
|
||||
|
||||
@@ -128,6 +128,7 @@ static void toggle_full_screen(struct sdl2_console *scon);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static bool g_android_gl_bgra_supported = true;
|
||||
static bool g_android_force_finish_before_swap = false;
|
||||
static bool g_android_paused = false;
|
||||
static bool g_android_should_quit = false;
|
||||
static uint64_t g_android_frame_counter = 0;
|
||||
@@ -218,6 +219,8 @@ static void sdl2_gl_render_texture(struct sdl2_console *scon,
|
||||
{
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
int ww = 0;
|
||||
int wh = 0;
|
||||
int vx = 0;
|
||||
int vy = 0;
|
||||
int vw;
|
||||
@@ -232,6 +235,7 @@ static void sdl2_gl_render_texture(struct sdl2_console *scon,
|
||||
android_log_gl_error("blit-start");
|
||||
|
||||
SDL_GL_GetDrawableSize(scon->real_window, &w, &h);
|
||||
SDL_GetWindowSize(scon->real_window, &ww, &wh);
|
||||
if (w <= 0) {
|
||||
w = 1;
|
||||
}
|
||||
@@ -255,6 +259,15 @@ static void sdl2_gl_render_texture(struct sdl2_console *scon,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if ((g_android_frame_counter % 60) == 0) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "xemu-android",
|
||||
"present drawable=%dx%d window=%dx%d viewport=%d,%d %dx%d tex=%u flip=%d mode=%d",
|
||||
w, h, ww, wh, vx, vy, vw, vh,
|
||||
(unsigned)tex, flip ? 1 : 0, g_android_display_mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(vx, vy, vw, vh);
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
@@ -969,6 +982,7 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
|
||||
int min_window_height = 480;
|
||||
int window_width = min_window_width;
|
||||
int window_height = min_window_height;
|
||||
SDL_DisplayMode disp_mode;
|
||||
|
||||
const int res_table[][2] = {
|
||||
{640, 480},
|
||||
@@ -998,6 +1012,22 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
|
||||
window_height = min_window_height;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* Android should always present into the full activity surface. Using the
|
||||
* desktop-style startup window size here lets narrow-height devices fall
|
||||
* into the "display smaller than requested window" path and clamps the SDL
|
||||
* window to 640x480, which is exactly the bottom-left tiny box symptom.
|
||||
*/
|
||||
if (SDL_GetCurrentDisplayMode(0, &disp_mode) == 0) {
|
||||
if (disp_mode.w > 0) {
|
||||
window_width = disp_mode.w;
|
||||
}
|
||||
if (disp_mode.h > 0) {
|
||||
window_height = disp_mode.h;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// On Android, always use OpenGL window even for Vulkan because Vulkan
|
||||
// needs GL context for external memory display presentation
|
||||
#ifdef __ANDROID__
|
||||
@@ -1021,12 +1051,13 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
|
||||
g_free(title);
|
||||
SDL_SetWindowMinimumSize(m_window, min_window_width, min_window_height);
|
||||
|
||||
SDL_DisplayMode disp_mode;
|
||||
SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(m_window), &disp_mode);
|
||||
#ifndef __ANDROID__
|
||||
if (disp_mode.w < window_width || disp_mode.h < window_height) {
|
||||
SDL_SetWindowSize(m_window, min_window_width, min_window_height);
|
||||
SDL_SetWindowPosition(m_window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_context = SDL_GL_CreateContext(m_window);
|
||||
|
||||
@@ -1111,6 +1142,12 @@ static void sdl2_display_very_early_init(DisplayOptions *o)
|
||||
__android_log_print(ANDROID_LOG_INFO, "xemu-android",
|
||||
"GL_EXT_texture_format_BGRA8888=%s",
|
||||
g_android_gl_bgra_supported ? "yes" : "no");
|
||||
if ((vendor && strstr(vendor, "ARM")) ||
|
||||
(renderer && strstr(renderer, "Mali"))) {
|
||||
g_android_force_finish_before_swap = true;
|
||||
__android_log_print(ANDROID_LOG_INFO, "xemu-android",
|
||||
"android: force glFinish before swap enabled");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1318,7 +1355,7 @@ void xemu_android_display_loop(void)
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
xemu_android_refresh_frame_limit_from_env();
|
||||
SDL_GL_SetSwapInterval(g_config.display.window.vsync ? 1 : 0);
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
xemu_hud_init(m_window, m_context);
|
||||
#endif
|
||||
tcg_register_init_ctx();
|
||||
@@ -1641,7 +1678,11 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
|
||||
qemu_mutex_unlock_main_loop();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
glFlush();
|
||||
if (g_android_force_finish_before_swap) {
|
||||
glFinish();
|
||||
} else {
|
||||
glFlush();
|
||||
}
|
||||
#else
|
||||
glFinish();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user