1 /* 2 Copyright (c) 2013 yvt 3 Portion of the code is based on Serverbrowser.cpp. 4 5 This file is part of OpenSpades. 6 7 OpenSpades is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 OpenSpades is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with OpenSpades. If not, see <http://www.gnu.org/licenses/>. 19 20 */ 21 22 #include <algorithm> 23 #include <cctype> 24 #include <utility> 25 #include <regex> 26 27 #include <Imports/OpenGL.h> //for gpu info 28 #include <Imports/SDL.h> 29 #include <json/json.h> 30 31 #include "StartupScreenHelper.h" 32 33 #include "StartupScreen.h" 34 #include <Audio/ALDevice.h> 35 #include <Audio/YsrDevice.h> 36 #include <Core/FileManager.h> 37 #include <Core/Settings.h> 38 #include <OpenSpades.h> 39 #include <Core/ShellApi.h> 40 #include <Gui/Main.h> 41 #include <Gui/Icon.h> 42 #include <Gui/PackageUpdateManager.h> 43 44 SPADES_SETTING(r_bloom); 45 SPADES_SETTING(r_lens); 46 SPADES_SETTING(r_cameraBlur); 47 SPADES_SETTING(r_softParticles); 48 SPADES_SETTING(r_mapSoftShadow); 49 SPADES_SETTING(r_modelShadows); 50 SPADES_SETTING(r_radiosity); 51 SPADES_SETTING(r_dlights); 52 SPADES_SETTING(r_water); 53 SPADES_SETTING(r_multisamples); 54 SPADES_SETTING(r_fxaa); 55 SPADES_SETTING(r_videoWidth); 56 SPADES_SETTING(r_videoHeight); 57 SPADES_SETTING(r_fullscreen); 58 SPADES_SETTING(r_fogShadow); 59 SPADES_SETTING(r_lensFlare); 60 SPADES_SETTING(r_lensFlareDynamic); 61 SPADES_SETTING(r_blitFramebuffer); 62 SPADES_SETTING(r_srgb); 63 SPADES_SETTING(r_shadowMapSize); 64 SPADES_SETTING(s_maxPolyphonics); 65 SPADES_SETTING(s_eax); 66 SPADES_SETTING(r_maxAnisotropy); 67 SPADES_SETTING(r_colorCorrection); 68 SPADES_SETTING(r_physicalLighting); 69 SPADES_SETTING(r_occlusionQuery); 70 SPADES_SETTING(r_depthOfField); 71 SPADES_SETTING(r_vsync); 72 SPADES_SETTING(r_renderer); 73 SPADES_SETTING(r_swUndersampling); 74 SPADES_SETTING(r_hdr); 75 76 namespace spades { 77 namespace gui { 78 StartupScreenHelper()79 StartupScreenHelper::StartupScreenHelper() 80 : scr(nullptr), 81 shaderHighCapable(false), 82 postFilterHighCapable(false), 83 particleHighCapable(false) { 84 SPADES_MARK_FUNCTION(); 85 } 86 ~StartupScreenHelper()87 StartupScreenHelper::~StartupScreenHelper() { SPADES_MARK_FUNCTION(); } 88 StartupScreenDestroyed()89 void StartupScreenHelper::StartupScreenDestroyed() { 90 SPADES_MARK_FUNCTION(); 91 scr = nullptr; 92 } 93 ExamineSystem()94 void StartupScreenHelper::ExamineSystem() { 95 SPADES_MARK_FUNCTION(); 96 97 // clear capability report 98 // (this function can be called multiple times via StartupScreenHelper::FixConfig) 99 reportLines.clear(); 100 report.clear(); 101 102 // check installed locales 103 SPLog("Checking installed locales"); 104 105 auto localeDirectories = FileManager::EnumFiles("Locales"); 106 locales.clear(); 107 for (const std::string &localeInfoName : localeDirectories) { 108 static std::regex localeInfoRegex("[-a-zA-Z0-9_]+\\.json"); 109 if (!std::regex_match(localeInfoName, localeInfoRegex)) { 110 continue; 111 } 112 std::string locale = localeInfoName.substr(0, localeInfoName.size() - 5); 113 std::string localeInfoPath = "Locales/" + localeInfoName; 114 115 try { 116 std::string buffer = FileManager::ReadAllBytes(localeInfoPath.c_str()); 117 LocaleInfo info; 118 Json::Reader reader; 119 Json::Value root; 120 if (!reader.parse(buffer.c_str(), root, false)) { 121 SPRaise("Failed to parse LocaleInfo.json: %s", 122 reader.getFormatedErrorMessages().c_str()); 123 } 124 125 info.name = locale; 126 info.descriptionEnglish = root["descriptionEnglish"].asString(); 127 info.descriptionNative = root["description"].asString(); 128 129 locales.push_back(std::move(info)); 130 131 SPLog("Locale '%s' found.", locale.c_str()); 132 } catch (const std::exception &ex) { 133 SPLog("Error while reading the locale info for '%s': %s", locale.c_str(), 134 ex.what()); 135 } 136 } 137 138 // check audio device availability 139 // Note: this only checks whether these libraries can be loaded. 140 141 SPLog("Checking YSR availability"); 142 if (!audio::YsrDevice::TryLoadYsr()) { 143 incapableConfigs.insert( 144 std::make_pair("s_audioDriver", [](std::string value) -> std::string { 145 if (EqualsIgnoringCase(value, "ysr")) { 146 return "YSR library couldn't be loaded."; 147 } else { 148 return std::string(); 149 } 150 })); 151 } 152 153 SPLog("Checking OpenAL availability"); 154 if (!audio::ALDevice::TryLoad()) { 155 incapableConfigs.insert( 156 std::make_pair("s_audioDriver", [](std::string value) -> std::string { 157 if (EqualsIgnoringCase(value, "openal")) { 158 return "OpenAL library couldn't be loaded."; 159 } else { 160 return std::string(); 161 } 162 })); 163 } 164 165 // check GL capabilities 166 167 SPLog("Performing ecapability query"); 168 169 int idDisplay = 0; 170 171 int numDisplayMode = SDL_GetNumDisplayModes(idDisplay); 172 SDL_DisplayMode mode; 173 modes.clear(); 174 if (numDisplayMode > 0) { 175 std::set<std::pair<int, int>> foundModes; 176 for (int i = 0; i < numDisplayMode; i++) { 177 SDL_GetDisplayMode(idDisplay, i, &mode); 178 if (mode.w < 800 || mode.h < 600) 179 continue; 180 if (foundModes.find(std::make_pair(mode.w, mode.h)) != foundModes.end()) 181 continue; 182 183 foundModes.insert(std::make_pair(mode.w, mode.h)); 184 modes.push_back(spades::IntVector3::Make(mode.w, mode.h, 0)); 185 SPLog("Video Mode Found: %dx%d", mode.w, mode.h); 186 } 187 } else { 188 SPLog("Failed to get video mode list. Presetting default list"); 189 modes.push_back(spades::IntVector3::Make(800, 600, 0)); 190 modes.push_back(spades::IntVector3::Make(1024, 768, 0)); 191 modes.push_back(spades::IntVector3::Make(1280, 720, 0)); 192 modes.push_back(spades::IntVector3::Make(1920, 1080, 0)); 193 } 194 195 bool capable = true; 196 SDL_Window *window = SDL_CreateWindow("OpenSpades: Please wait...", 1, 1, 1, 1, 197 SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS); 198 if (window == nullptr) { 199 SPLog("Failed to create SDL window: %s", SDL_GetError()); 200 } 201 SDL_GLContext context = window ? SDL_GL_CreateContext(window) : nullptr; 202 if (window != nullptr && context == nullptr) { 203 SPLog("Failed to create OpenGL context: %s", SDL_GetError()); 204 } 205 206 #ifdef __APPLE__ 207 #elif __unix 208 SDL_Surface *icon = nullptr; 209 SDL_RWops *icon_rw = nullptr; 210 icon_rw = SDL_RWFromConstMem(g_appIconData, GetAppIconDataSize()); 211 if (icon_rw != nullptr) { 212 icon = IMG_LoadPNG_RW(icon_rw); 213 SDL_FreeRW(icon_rw); 214 } 215 if (icon == nullptr) { 216 std::string msg = SDL_GetError(); 217 SPLog("Failed to load icon: %s", msg.c_str()); 218 } else { 219 SDL_SetWindowIcon(window, icon); 220 SDL_FreeSurface(icon); 221 } 222 #endif 223 224 if (!context) { 225 // OpenGL initialization failed! 226 227 std::string err = SDL_GetError(); 228 SPLog("SDL_SetVideoMode failed: %s", err.c_str()); 229 230 AddReport("OpenGL-capable graphics accelerator is unavailable.", 231 MakeVector4(1.f, 0.5f, 0.5f, 1.f)); 232 233 AddReport(); 234 235 AddReport("OpenGL/SDL couldn't be initialized."); 236 AddReport("Falling back to the software renderer."); 237 238 AddReport(); 239 AddReport("Message from SDL:", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 240 AddReport(err, MakeVector4(1.f, 1.f, 1.f, 0.7f)); 241 242 capable = false; 243 shaderHighCapable = false; 244 postFilterHighCapable = false; 245 particleHighCapable = false; 246 } else { 247 248 SDL_GL_MakeCurrent(window, context); 249 250 shaderHighCapable = true; 251 postFilterHighCapable = true; 252 particleHighCapable = true; 253 254 const char *str; 255 GLint maxTextureSize; 256 GLint max3DTextureSize; 257 GLint maxCombinedTextureUnits; 258 GLint maxVertexTextureUnits; 259 GLint maxVaryingComponents; 260 SPLog("--- OpenGL Renderer Info ---"); 261 262 AddReport("OpenGL-capable graphics accelerator is available."); 263 264 if ((str = (const char *)glGetString(GL_VENDOR)) != NULL) { 265 SPLog("Vendor: %s", str); 266 AddReport(std::string("Vendor: ") + str, MakeVector4(1.f, 1.f, 1.f, 0.7f)); 267 } 268 if ((str = (const char *)glGetString(GL_RENDERER)) != NULL) { 269 SPLog("Name: %s", str); 270 AddReport(std::string("Name: ") + str, MakeVector4(1.f, 1.f, 1.f, 0.7f)); 271 } 272 if ((str = (const char *)glGetString(GL_VERSION)) != NULL) { 273 AddReport(std::string("Version: ") + str, MakeVector4(1.f, 1.f, 1.f, 0.7f)); 274 SPLog("Version: %s", str); 275 } 276 if ((str = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION)) != NULL) { 277 AddReport(std::string("GLSL Version: ") + str, 278 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 279 SPLog("Shading Language Version: %s", str); 280 } 281 282 AddReport(); 283 284 maxTextureSize = 0; 285 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 286 if (maxTextureSize > 0) { 287 SPLog("Max Texture Size: %d", (int)maxTextureSize); 288 } 289 max3DTextureSize = 0; 290 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DTextureSize); 291 if (max3DTextureSize > 0) { 292 SPLog("Max 3D Texture Size: %d", (int)max3DTextureSize); 293 } 294 295 maxCombinedTextureUnits = 0; 296 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureUnits); 297 if (maxCombinedTextureUnits > 0) { 298 SPLog("Max Combined Texture Image Units: %d", (int)maxCombinedTextureUnits); 299 } 300 301 maxVertexTextureUnits = 0; 302 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureUnits); 303 if (maxVertexTextureUnits > 0) { 304 SPLog("Max Vertex Texture Image Units: %d", (int)maxVertexTextureUnits); 305 } 306 307 maxVaryingComponents = 0; 308 glGetIntegerv(GL_MAX_VARYING_COMPONENTS, &maxVaryingComponents); 309 if (maxVaryingComponents > 0) { 310 SPLog("Max Varying Components: %d", (int)maxVaryingComponents); 311 } 312 313 str = (const char *)glGetString(GL_EXTENSIONS); 314 std::string extensions; 315 if (str) 316 extensions = str; 317 const char *const requiredExtensions[] = {"GL_ARB_multitexture", 318 "GL_ARB_shader_objects", 319 "GL_ARB_shading_language_100", 320 "GL_ARB_texture_non_power_of_two", 321 "GL_ARB_vertex_buffer_object", 322 "GL_EXT_framebuffer_object", 323 NULL}; 324 325 SPLog("--- Extensions ---"); 326 std::vector<std::string> strs = spades::Split(str, " "); 327 for (size_t i = 0; i < strs.size(); i++) { 328 SPLog("%s", strs[i].c_str()); 329 } 330 SPLog("------------------"); 331 332 for (size_t i = 0; requiredExtensions[i]; i++) { 333 const char *ex = requiredExtensions[i]; 334 if (extensions.find(ex) == std::string::npos) { 335 // extension not found 336 AddReport(std::string(ex) + " is NOT SUPPORTED!", 337 MakeVector4(1.f, 0.5f, 0.5f, 1.f)); 338 capable = false; 339 } 340 } 341 342 // non-requred extensions 343 if (extensions.find("GL_ARB_framebuffer_sRGB") == std::string::npos) { 344 if (r_srgb) { 345 r_srgb = 0; 346 SPLog("Disabling r_srgb: no GL_ARB_framebuffer_sRGB"); 347 } 348 349 incapableConfigs.insert( 350 std::make_pair("r_srgb", [](std::string value) -> std::string { 351 if (std::stoi(value) != 0) { 352 return "SRGB framebuffer is disabled because your video card doesn't " 353 "support GL_ARB_framebuffer_sRGB."; 354 } else { 355 return std::string(); 356 } 357 })); 358 359 AddReport("GL_ARB_framebuffer_sRGB is NOT SUPPORTED", 360 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 361 AddReport(" r_srgb is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 362 } 363 if (extensions.find("GL_EXT_framebuffer_blit") == std::string::npos) { 364 if (r_blitFramebuffer) { 365 r_blitFramebuffer = 0; 366 SPLog("Disabling r_blitFramebuffer: no GL_EXT_framebuffer_blit"); 367 } 368 if (r_multisamples) { 369 r_multisamples = 0; 370 SPLog("Disabling r_multisamples: no GL_EXT_framebuffer_blit"); 371 } 372 incapableConfigs.insert( 373 std::make_pair("r_blitFramebuffer", [](std::string value) -> std::string { 374 if (std::stoi(value) != 0) { 375 return "r_blitFramebuffer is disabled because your video card " 376 "doesn't support GL_EXT_framebuffer_blit."; 377 } else { 378 return std::string(); 379 } 380 })); 381 382 AddReport("GL_EXT_framebuffer_blit is NOT SUPPORTED", 383 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 384 AddReport(" r_blitFramebuffer is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 385 } 386 if (extensions.find("GL_EXT_texture_filter_anisotropic") == std::string::npos) { 387 if ((float)r_maxAnisotropy > 1.1f) { 388 r_maxAnisotropy = 1; 389 SPLog("Setting r_maxAnisotropy to 1: no GL_EXT_texture_filter_anisotropic"); 390 } 391 392 incapableConfigs.insert( 393 std::make_pair("r_maxAnisotropy", [](std::string value) -> std::string { 394 if (std::stof(value) > 1.001f) { 395 return "Anisotropic texture filtering is disabled because your video " 396 "card doesn't support GL_EXT_texture_filter_anisotropic."; 397 } else { 398 return std::string(); 399 } 400 })); 401 AddReport("GL_EXT_texture_filter_anisotropic is NOT SUPPORTED", 402 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 403 AddReport(" r_maxAnisotropy is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 404 } 405 406 if (extensions.find("GL_ARB_occlusion_query") == std::string::npos) { 407 if (r_occlusionQuery) { 408 r_occlusionQuery = 0; 409 SPLog("Disabling r_occlusionQuery: no GL_ARB_occlusion_query"); 410 } 411 incapableConfigs.insert( 412 std::make_pair("r_occlusionQuery", [](std::string value) -> std::string { 413 if (std::stoi(value)) { 414 return "Occlusion query is disabled because your video card doesn't " 415 "support GL_ARB_occlusion_query."; 416 } else { 417 return std::string(); 418 } 419 })); 420 AddReport("GL_ARB_occlusion_query is NOT SUPPORTED", 421 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 422 AddReport(" r_occlusionQuery is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 423 } 424 425 if (extensions.find("GL_NV_conditional_render") == std::string::npos) { 426 if (r_occlusionQuery) { 427 r_occlusionQuery = 0; 428 SPLog("Disabling r_occlusionQuery: no GL_NV_conditional_render"); 429 } 430 incapableConfigs.insert( 431 std::make_pair("r_occlusionQuery", [](std::string value) -> std::string { 432 if (std::stoi(value)) { 433 return "Occlusion query is disabled because your video card doesn't " 434 "support GL_NV_conditional_render."; 435 } else { 436 return std::string(); 437 } 438 })); 439 AddReport("GL_NV_conditional_render is NOT SUPPORTED", 440 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 441 AddReport(" r_occlusionQuery is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 442 } 443 444 if (extensions.find("GL_ARB_color_buffer_float") == std::string::npos) { 445 if (r_hdr) { 446 r_hdr = 0; 447 SPLog("Disabling r_hdr: no GL_ARB_color_buffer_float"); 448 } 449 incapableConfigs.insert( 450 std::make_pair("r_hdr", [](std::string value) -> std::string { 451 if (std::stoi(value)) { 452 return "HDR Rendering is disabled because your video card doesn't " 453 "support GL_ARB_color_buffer_float."; 454 } else { 455 return std::string(); 456 } 457 })); 458 AddReport("GL_ARB_color_buffer_float is NOT SUPPORTED", 459 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 460 AddReport(" r_hdr is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 461 } 462 463 if (extensions.find("GL_EXT_texture_array") == std::string::npos) { 464 if ((int)r_water >= 2) { 465 r_water = 1; 466 SPLog("Disabling Water 2: no GL_EXT_texture_array"); 467 } 468 shaderHighCapable = false; 469 incapableConfigs.insert( 470 std::make_pair("r_water", [](std::string value) -> std::string { 471 if (std::stoi(value) >= 2) { 472 return "Water 2 is disabled because your video card doesn't " 473 "support GL_EXT_texture_array."; 474 } else { 475 return std::string(); 476 } 477 })); 478 AddReport("GL_EXT_texture_array is NOT SUPPORTED", 479 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 480 AddReport(" Water 2 is disabled.", MakeVector4(1.f, 1.f, 1.f, 0.7f)); 481 } 482 483 AddReport("Max Texture Size: " + std::to_string(maxTextureSize), 484 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 485 if (maxTextureSize < 1024) { 486 capable = false; 487 AddReport(" TOO SMALL (1024 required)", MakeVector4(1.f, 0.5f, 0.5f, 1.f)); 488 } 489 if ((int)r_shadowMapSize > maxTextureSize) { 490 SPLog("Changed r_shadowMapSize from %d to %d: too small GL_MAX_TEXTURE_SIZE", 491 (int)r_shadowMapSize, maxTextureSize); 492 493 r_shadowMapSize = maxTextureSize; 494 } 495 496 AddReport("Max 3D Texture Size: " + std::to_string(max3DTextureSize), 497 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 498 if (max3DTextureSize < 512) { 499 AddReport(" Global Illumination is disabled (512 required)", 500 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 501 incapableConfigs.insert( 502 std::make_pair("r_radiosity", [](std::string value) -> std::string { 503 if (std::stoi(value)) { 504 return "Global illumination is disabled because your video card " 505 "doesn't support a 3D texture of at least 512x512x64."; 506 } else { 507 return std::string(); 508 } 509 })); 510 511 if (r_radiosity) { 512 r_radiosity = 0; 513 SPLog("Disabling r_radiosity: too small GL_MAX_3D_TEXTURE_SIZE"); 514 } 515 } 516 517 AddReport("Max Combined Texture Image Units: " + 518 std::to_string(maxCombinedTextureUnits), 519 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 520 if (maxCombinedTextureUnits < 12) { 521 AddReport(" Global Illumination is disabled (12 required)", 522 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 523 incapableConfigs.insert( 524 std::make_pair("r_radiosity", [](std::string value) -> std::string { 525 if (std::stoi(value)) { 526 return "Global illumination is disabled because your video card " 527 "supports too few combined texture image units."; 528 } else { 529 return std::string(); 530 } 531 })); 532 533 if (r_radiosity) { 534 r_radiosity = 0; 535 SPLog( 536 "Disabling r_radiosity: too small GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"); 537 } 538 } 539 if (maxCombinedTextureUnits < 15) { 540 AddReport(" Water 2 is disabled (15 required)", 541 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 542 shaderHighCapable = false; 543 544 incapableConfigs.insert( 545 std::make_pair("r_water", [](std::string value) -> std::string { 546 if (std::stoi(value) >= 2) { 547 return "Water 2 is disabled because your video card supports too few " 548 "combined texture image units."; 549 } else { 550 return std::string(); 551 } 552 })); 553 554 if ((int)r_water >= 2) { 555 r_water = 1; 556 SPLog("Disabling Water 2: too small GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS"); 557 } 558 } 559 560 AddReport("Max Vertex Texture Image Units: " + 561 std::to_string(maxVertexTextureUnits), 562 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 563 if (maxVertexTextureUnits < 3) { 564 AddReport(" Water 2 is disabled (3 required)", 565 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 566 shaderHighCapable = false; 567 568 incapableConfigs.insert( 569 std::make_pair("r_water", [](std::string value) -> std::string { 570 if (std::stoi(value) >= 2) { 571 return "Water 2 is disabled because your video card supports too few " 572 "vertex texture image units."; 573 } else { 574 return std::string(); 575 } 576 })); 577 578 if ((int)r_water >= 2) { 579 r_water = 1; 580 SPLog("Disabling Water 2: too small GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"); 581 } 582 } 583 584 AddReport("Max Varying Components: " + std::to_string(maxVaryingComponents), 585 MakeVector4(1.f, 1.f, 1.f, 0.7f)); 586 if (maxVaryingComponents < 37) { 587 AddReport(" Shaded Particle is disabled (37 required)", 588 MakeVector4(1.f, 1.f, 0.5f, 1.f)); 589 particleHighCapable = false; 590 591 incapableConfigs.insert( 592 std::make_pair("r_softParticles", [](std::string value) -> std::string { 593 if (std::stoi(value) >= 2) { 594 return "Shaded particle is disabled because your video card supports " 595 "too few varying fragment shader input components."; 596 } else { 597 return std::string(); 598 } 599 })); 600 601 if ((int)r_softParticles >= 2) { 602 r_softParticles = 1; 603 SPLog( 604 "Disabling shaded particle: too small GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS"); 605 } 606 } 607 608 AddReport(); 609 610 if (capable) { 611 AddReport("Your video card supports all " 612 "required OpenGL extensions/features.", 613 MakeVector4(0.5f, 1.f, 0.5f, 1.f)); 614 } else { 615 AddReport("Your video card/driver doesn't support " 616 "at least one of required OpenGL extensions/features." 617 " Falling back to the software renderer.", 618 MakeVector4(1.f, 0.5f, 0.5f, 1.f)); 619 } 620 621 SDL_GL_DeleteContext(context); 622 SDL_DestroyWindow(window); 623 624 SPLog("SDL Capability Query Window finalized"); 625 } 626 627 SPLog("OpenGL driver is OpenSpades capable: %s", capable ? "YES" : "NO"); 628 629 openGLCapable = capable; 630 if (!openGLCapable) { 631 if (spades::EqualsIgnoringCase(r_renderer, "gl")) { 632 SPLog("Switched to software renderer"); 633 r_renderer = "sw"; 634 } 635 636 incapableConfigs.insert( 637 std::make_pair("r_renderer", [](std::string value) -> std::string { 638 if (spades::EqualsIgnoringCase(value, "gl")) { 639 return "OpenGL renderer is disabled because " 640 "your video card/driver doesn't support " 641 "at least one of required OpenGL extensions/features."; 642 } else { 643 return std::string(); 644 } 645 })); 646 } 647 } 648 FixConfigs()649 void StartupScreenHelper::FixConfigs() { ExamineSystem(); } 650 GetOperatingSystemType()651 std::string StartupScreenHelper::GetOperatingSystemType() { 652 #if defined(OS_PLATFORM_LINUX) 653 return "Linux"; 654 #elif defined(TARGET_OS_MAC) 655 return "Mac"; 656 #elif defined(OS_PLATFORM_WINDOWS) 657 return "Windows"; 658 #elif defined(__FreeBSD__) 659 return "FreeBSD"; 660 #elif defined(__OpenBSD__) 661 return "OpenBSD"; 662 #else 663 return std::string{}; 664 #endif 665 } 666 GetPackageUpdateManager()667 PackageUpdateManager& StartupScreenHelper::GetPackageUpdateManager() { 668 return PackageUpdateManager::GetInstance(); 669 } 670 OpenUpdateInfoURL()671 bool StartupScreenHelper::OpenUpdateInfoURL() { 672 std::string url = GetPackageUpdateManager().GetLatestVersionInfoPageURL(); 673 if (url.find("http:") != 0 && url.find("https:") != 0) { 674 return false; 675 } 676 return OpenURLInBrowser(url); 677 } 678 BrowseUserDirectory()679 bool StartupScreenHelper::BrowseUserDirectory() { 680 std::string path = g_userResourceDirectory; 681 682 if (path.empty()) { 683 SPLog("Cannot open the user resource directory: g_userResourceDirectory is empty."); 684 return false; 685 } 686 687 return ShowDirectoryInShell(path); 688 } 689 Start()690 void StartupScreenHelper::Start() { 691 if (scr == nullptr) { 692 return; 693 } 694 scr->Start(); 695 } 696 GetNumVideoModes()697 int StartupScreenHelper::GetNumVideoModes() { return static_cast<int>(modes.size()); } 698 GetVideoModeWidth(int index)699 int StartupScreenHelper::GetVideoModeWidth(int index) { 700 if (index < 0 || index >= GetNumVideoModes()) 701 SPInvalidArgument("index"); 702 return modes[index].x; 703 } GetVideoModeHeight(int index)704 int StartupScreenHelper::GetVideoModeHeight(int index) { 705 if (index < 0 || index >= GetNumVideoModes()) 706 SPInvalidArgument("index"); 707 return modes[index].y; 708 } 709 GetNumReportLines()710 int StartupScreenHelper::GetNumReportLines() { 711 return static_cast<int>(reportLines.size()); 712 } 713 GetReportLineText(int index)714 std::string StartupScreenHelper::GetReportLineText(int index) { 715 if (index < 0 || index >= GetNumReportLines()) 716 SPInvalidArgument("index"); 717 return reportLines[index].text; 718 } GetReportLineColor(int index)719 Vector4 StartupScreenHelper::GetReportLineColor(int index) { 720 if (index < 0 || index >= GetNumReportLines()) 721 SPInvalidArgument("index"); 722 return reportLines[index].color; 723 } 724 AddReport(const std::string & text,Vector4 color)725 void StartupScreenHelper::AddReport(const std::string &text, Vector4 color) { 726 ReportLine l = {text, color}; 727 reportLines.push_back(l); 728 report += text; 729 report += '\n'; 730 } 731 GetNumLocales()732 int StartupScreenHelper::GetNumLocales() { return static_cast<int>(locales.size()); } GetLocale(int index)733 std::string StartupScreenHelper::GetLocale(int index) { 734 if (index < 0 || index >= GetNumLocales()) 735 SPInvalidArgument("index"); 736 return locales[index].name; 737 } GetLocaleDescriptionNative(int index)738 std::string StartupScreenHelper::GetLocaleDescriptionNative(int index) { 739 if (index < 0 || index >= GetNumLocales()) 740 SPInvalidArgument("index"); 741 return locales[index].descriptionNative; 742 } GetLocaleDescriptionEnglish(int index)743 std::string StartupScreenHelper::GetLocaleDescriptionEnglish(int index) { 744 if (index < 0 || index >= GetNumLocales()) 745 SPInvalidArgument("index"); 746 return locales[index].descriptionEnglish; 747 } 748 CheckConfigCapability(const std::string & cfg,const std::string & value)749 std::string StartupScreenHelper::CheckConfigCapability(const std::string &cfg, 750 const std::string &value) { 751 auto range = incapableConfigs.equal_range(cfg); 752 std::string ret; 753 bool hasMulti = false; 754 for (auto it = range.first; it != range.second; it++) { 755 auto &f = it->second; 756 auto err = f(value); 757 if (err.size() > 0) { 758 if (ret.size() == 0) { 759 ret = err; 760 } else { 761 if (!hasMulti) { 762 ret = "- " + ret; 763 hasMulti = true; 764 } 765 ret += "\n- " + err; 766 } 767 } 768 } 769 return ret; 770 } 771 } 772 } 773