windows: detect intel's shitty driver and fall back to ANGLE

This commit is contained in:
Andrei Alexeyev 2019-09-21 16:39:05 +03:00
parent 1fdc00fc39
commit 7fe3f8ff90
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
12 changed files with 203 additions and 32 deletions

View file

@ -9,11 +9,10 @@ charset = utf-8
indent_style = tab
# indent_size = 4
[*.{py,html,js}]
[*.{py,html,js,nsi.in}]
indent_style = space
indent_size = 4
[meson.build]
indent_style = space
indent_size = 4

View file

@ -1,10 +1,2 @@
@echo off
cd "%~dp0"
set ANGLE_PATH=.\ANGLE
set TAISEI_RENDERER=gles30
set SDL_OPENGL_ES_DRIVER=1
set SDL_VIDEO_GL_DRIVER=%ANGLE_PATH%\libGLESv2.dll
set SDL_VIDEO_EGL_DRIVER=%ANGLE_PATH%\libEGL.dll
start .\taisei.exe %*
"%~dp0\taisei.exe" --renderer gles30 %*

View file

@ -155,20 +155,17 @@ Section "-Core installation"
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei.lnk" "$INSTDIR\taisei.exe"
!if @USE_ANGLE@ == 1
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (OpenGL).lnk" "$INSTDIR\taisei.exe"
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (ANGLE).lnk" "$INSTDIR\taisei-angle.bat" "" "$INSTDIR\taisei.exe" 0 SW_SHOWMINIMIZED
!else
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei.lnk" "$INSTDIR\taisei.exe"
CreateShortcut "$SMPROGRAMS\$STARTMENU_FOLDER\Taisei (ANGLE).lnk" "$INSTDIR\taisei.exe" "--renderer gles30"
!endif
${If} "$INSTALL_DESKTOP" == "1"
CreateShortcut "$DESKTOP\Taisei.lnk" "$INSTDIR\taisei.exe"
!if @USE_ANGLE@ == 1
CreateShortcut "$DESKTOP\Taisei (OpenGL).lnk" "$INSTDIR\taisei.exe"
CreateShortcut "$DESKTOP\Taisei (ANGLE).lnk" "$INSTDIR\taisei-angle.bat" "" "$INSTDIR\taisei.exe" 0 SW_SHOWMINIMIZED
!else
CreateShortcut "$DESKTOP\Taisei.lnk" "$INSTDIR\taisei.exe"
CreateShortcut "$DESKTOP\Taisei (ANGLE).lnk" "$INSTDIR\taisei.exe" "--renderer gles30"
!endif
${EndIf}
@ -257,7 +254,7 @@ Function .onInit
StrCmp $0 "" inst
MessageBox MB_YESNOCANCEL|MB_ICONEXCLAMATION \
"${APPNAME} is already installed. $\n$\nDo you want to uninstall the old version before installing the new one?" \
"${APPNAME} is already installed.$\n$\nDo you want to uninstall the old version before installing the new one?$\n$\nIf unsure, choose YES." \
/SD IDYES IDYES uninst IDNO inst
Abort

View file

@ -19,27 +19,53 @@
struct TsOption { struct option opt; const char *help; const char *argname;};
enum {
OPT_RENDERER = INT_MIN,
};
static void print_help(struct TsOption* opts) {
tsfprintf(stdout, "Usage: taisei [OPTIONS]\nTaisei is an open source Tōhō Project fangame.\n\nOptions:\n");
int margin = 20;
for(struct TsOption *opt = opts; opt->opt.name; opt++) {
tsfprintf(stdout, " -%c, --%s ", opt->opt.val,opt->opt.name);
if(opt->opt.val > 0) {
tsfprintf(stdout, " -%c, --%s ", opt->opt.val, opt->opt.name);
} else {
tsfprintf(stdout, " --%s ", opt->opt.name);
}
int length = margin-(int)strlen(opt->opt.name);
if(opt->argname) {
tsfprintf(stdout, "%s", opt->argname);
length -= (int)strlen(opt->argname);
}
for(int i = 0; i < length; i++)
tsfprintf(stdout, " ");
if(opt->argname)
for(int i = 0; i < length; i++) {
fputc(' ', stdout);
}
fputs(" ", stdout);
if(opt->argname && strchr(opt->help, '%')) {
tsfprintf(stdout, opt->help, opt->argname);
else
} else {
tsfprintf(stdout, "%s", opt->help);
}
tsfprintf(stdout, "\n");
}
}
int cli_args(int argc, char **argv, CLIAction *a) {
const char *const _renderer_list =
#define R(r) ","#r
TAISEI_BUILDCONF_RENDERER_BACKENDS
#undef R
;
char renderer_list[strlen(_renderer_list) + 2];
snprintf(renderer_list, sizeof(renderer_list), "{%s}", _renderer_list+1);
struct TsOption taisei_opts[] = {
{{"replay", required_argument, 0, 'r'}, "Play a replay from %s", "FILE"},
{{"verify-replay", required_argument, 0, 'R'}, "Play a replay from %s in headless mode, crash as soon as it desyncs", "FILE"},
@ -53,6 +79,7 @@ int cli_args(int argc, char **argv, CLIAction *a) {
#endif
{{"frameskip", optional_argument, 0, 'f'}, "Disable FPS limiter, render only every %s frame", "FRAME"},
{{"credits", no_argument, 0, 'c'}, "Show the credits scene and exit"},
{{"renderer", required_argument, 0, OPT_RENDERER}, "Choose the rendering backend", renderer_list},
{{"help", no_argument, 0, 'h'}, "Display this help"},
{{0,0,0,0},0,0}
};
@ -66,6 +93,11 @@ int cli_args(int argc, char **argv, CLIAction *a) {
for(int i = 0; i < nopts; i++) {
opts[i] = taisei_opts[i].opt;
if(opts[i].val <= 0) {
continue;
}
*ptr = opts[i].val;
ptr++;
@ -160,8 +192,11 @@ int cli_args(int argc, char **argv, CLIAction *a) {
case 'c':
a->type = CLI_Credits;
break;
case OPT_RENDERER:
env_set("TAISEI_RENDERER", optarg, true);
break;
default:
log_fatal("Unknown option (this shouldnt happen)");
UNREACHABLE;
}
}

View file

@ -10,8 +10,15 @@ if host_machine.system() == 'windows'
winmod = import('windows')
rcpath = join_paths(meson.current_build_dir(), 'taisei.rc')
icons_dir = join_paths(meson.source_root(), 'misc', 'icons')
icon_main = join_paths(icons_dir, 'taisei.ico')
icon_replay = join_paths(icons_dir, 'taisei-replay.ico')
manifest = join_paths(meson.current_source_dir(), 'taisei.manifest')
rcdefs = [
'-DICONS_DIR=@0@'.format(join_paths(meson.source_root(), 'misc', 'icons'))
'-DICON_MAIN=@0@'.format(icon_main),
'-DICON_REPLAY=@0@'.format(icon_replay),
'-DMANIFEST=@0@'.format(manifest),
]
if is_debug_build
@ -28,12 +35,25 @@ if host_machine.system() == 'windows'
output : 'taisei.rc',
)
version_deps += winmod.compile_resources(rc_target)
if meson.version().version_compare('>=0.47.0')
version_deps += winmod.compile_resources(
rc_target,
depend_files : files(
'taisei.manifest',
icon_main,
icon_replay,
)
)
else
version_deps += winmod.compile_resources(rc_target)
endif
# msvcrt is dumb and only supports up to c89.
# with this defined, alternative implementations from mingw for e.g. the
# printf family of functions will be used, which conform to c11.
config.set('__USE_MINGW_ANSI_STDIO', 1)
taisei_deps += cc.find_library('comctl32')
endif
use_intel_intrin = get_option('intel_intrin') and cc.links('''

View file

@ -593,6 +593,78 @@ static APIENTRY GLvoid shim_glClearDepthf(GLfloat depthval) {
}
#endif
static void detect_broken_intel_driver(void) {
#ifdef TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK
extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
bool is_broken_intel_driver = (
!glext.version.is_es &&
strstartswith((const char*)glGetString(GL_VENDOR), "Intel") &&
strstr((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION), " - Build ")
);
if(!is_broken_intel_driver) {
return;
}
int button;
SDL_MessageBoxData mbdata = { 0 };
mbdata.flags = SDL_MESSAGEBOX_WARNING;
mbdata.title = "Taisei Project";
char *msg = strfmt(
"Looks like you have a broken OpenGL driver.\n"
"Taisei will probably not work correctly, if at all.\n\n"
"Starting the game in ANGLE mode should fix the problem, but may introduce slowdown.\n\n"
"Restart in ANGLE mode now? (If unsure, press YES)"
);
mbdata.message = msg;
mbdata.numbuttons = 3;
mbdata.buttons = (SDL_MessageBoxButtonData[]) {
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Abort" },
{ 0, 1, "No" },
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "Yes (safe)" },
};
int mbresult = SDL_ShowMessageBox(&mbdata, &button);
free(msg);
if(mbresult < 0) {
log_sdl_error(LOG_ERROR, "SDL_ShowMessageBox");
} else if(button == 1) {
return;
} else if(button == 2) {
exit(1);
}
const WCHAR *cmdline = GetCommandLine();
const WCHAR renderer_args[] = L" --renderer gles30";
WCHAR new_cmdline[wcslen(cmdline) + wcslen(renderer_args) + 1];
memcpy(new_cmdline, cmdline, sizeof(WCHAR) * wcslen(cmdline));
memcpy(new_cmdline + wcslen(cmdline), renderer_args, sizeof(renderer_args));
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
CreateProcessW(
NULL,
new_cmdline,
NULL,
NULL,
false,
0,
NULL,
NULL,
&si,
&pi
);
exit(0);
#endif
}
void glcommon_check_capabilities(void) {
memset(&glext, 0, sizeof(glext));
@ -632,6 +704,8 @@ void glcommon_check_capabilities(void) {
log_info("OpenGL renderer: %s", (const char*)glGetString(GL_RENDERER));
log_info("GLSL version: %s", glslv);
detect_broken_intel_driver();
// XXX: this is the legacy way, maybe we shouldn't try this first
const char *exts = (const char*)glGetString(GL_EXTENSIONS);

View file

@ -14,6 +14,20 @@
#include "../gl33/gl33.h"
void gles_init(RendererBackend *gles_backend, int major, int minor) {
#ifdef TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK
char *basepath = SDL_GetBasePath();
size_t basepath_len = strlen(basepath);
char buf[basepath_len + 32];
snprintf(buf, sizeof(buf), "%sANGLE\\", basepath);
SDL_free(basepath);
basepath_len += sizeof("ANGLE");
strlcpy(buf + basepath_len, "libGLESv2.dll", sizeof(buf) - basepath_len);
env_set("SDL_VIDEO_GL_DRIVER", buf, false);
strlcpy(buf + basepath_len, "libEGL.dll", sizeof(buf) - basepath_len);
env_set("SDL_VIDEO_EGL_DRIVER", buf, false);
env_set("SDL_OPENGL_ES_DRIVER", 1, false);
#endif
_r_backend_inherit(gles_backend, &_r_backend_gl33);
glcommon_setup_attributes(SDL_GL_CONTEXT_PROFILE_ES, major, minor, 0);
glcommon_load_library();

View file

@ -61,3 +61,8 @@ endforeach
r_macro = ' '.join(r_macro)
config.set('TAISEI_BUILDCONF_RENDERER_BACKENDS', r_macro)
config.set_quoted('TAISEI_BUILDCONF_RENDERER_DEFAULT', default_renderer)
config.set('TAISEI_BUILDCONF_HAVE_WINDOWS_ANGLE_FALLBACK',
host_machine.system() == 'windows' and
enabled_renderers.contains('gles30') and
get_option('install_angle')
)

30
src/taisei.manifest Normal file
View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Supports Windows Vista / Server 2008 -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Supports Windows 7 / Server 2008 R2 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Supports Windows 8 / Server 2012 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Supports Windows 8.1 / Server 2012 R2 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Supports Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
</assembly>

View file

@ -2,16 +2,19 @@
#define IDS_TAISEI 1
#define IDS_REPLAY 2
#include "winver.h"
#include <winver.h>
#include <windows.h>
IDI_ICON1 ICON "${ICONS_DIR}/taisei.ico"
IDI_ICON2 ICON "${ICONS_DIR}/taisei-replay.ico"
IDI_ICON1 ICON "${ICON_MAIN}"
IDI_ICON2 ICON "${ICON_REPLAY}"
STRINGTABLE BEGIN
IDS_TAISEI, "Taisei Project"
IDS_REPLAY, "Taisei Project replay"
END
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "${MANIFEST}"
${BUILDTYPE_DEFINE}
#ifdef DEBUG_BUILD

View file

@ -32,6 +32,7 @@ const char *env_get_string_nonempty(const char *var, const char *fallback) {
}
void env_set_string(const char *var, const char *val, bool override) {
log_debug("%s=%s (%i)", var, val, override);
SDL_setenv(var, val, override);
}

View file

@ -208,10 +208,11 @@ static void video_new_window_internal(uint display, uint w, uint h, uint32_t fla
title,
SDL_WINDOWPOS_CENTERED_DISPLAY(display),
SDL_WINDOWPOS_CENTERED_DISPLAY(display),
w, h, flags
w, h, flags | SDL_WINDOW_HIDDEN
);
if(video.window) {
SDL_ShowWindow(video.window);
SDL_SetWindowMinimumSize(video.window, SCREEN_W / 4, SCREEN_H / 4);
video_update_mode_settings();
return;