windows: detect intel's shitty driver and fall back to ANGLE
This commit is contained in:
parent
1fdc00fc39
commit
7fe3f8ff90
12 changed files with 203 additions and 32 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 %*
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
47
src/cli.c
47
src/cli.c
|
@ -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 shouldn’t happen)");
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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('''
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
30
src/taisei.manifest
Normal 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>
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue