diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -228,25 +228,52 @@ static void LoadSpriteTables() */ static void SwitchNewGRFBlitter() { - /* Get blitter of base set. */ - bool is_32bpp = BaseGraphics::GetUsedSet()->blitter == BLT_32BPP; + /* Never switch if the blitter was specified by the user. */ + if (!_blitter_autodetected) return; - /* Get combined blitter mode of all NewGRFs. */ + /* Null driver => dedicated server => do nothing. */ + if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return; + + /* Get preferred depth. */ + uint depth_wanted_by_base = BaseGraphics::GetUsedSet()->blitter == BLT_32BPP ? 32 : 8; + uint depth_wanted_by_grf = 8; for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) { if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND || HasBit(c->flags, GCF_INIT_ONLY)) continue; - - if (c->palette & GRFP_BLT_32BPP) is_32bpp = true; + if (c->palette & GRFP_BLT_32BPP) depth_wanted_by_grf = 32; } - /* A GRF would like a 32 bpp blitter, switch blitter if needed. Never switch if the blitter was specified by the user. */ - if (_blitter_autodetected && is_32bpp && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0 && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() < 16) { - const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName(); - if (BlitterFactory::SelectBlitter("32bpp-anim") != NULL) { - if (!_video_driver->AfterBlitterChange()) { - /* Failed to switch blitter, let's hope we can return to the old one. */ - if (BlitterFactory::SelectBlitter(cur_blitter) == NULL || !_video_driver->AfterBlitterChange()) usererror("Failed to reinitialize video driver for 32 bpp blitter. Specify a fixed blitter in the config"); - } - } + /* Search the best blitter. */ + struct { + const char *name; + uint min_base_depth, max_base_depth, min_grf_depth, max_grf_depth; + } replacement_blitters[] = { +#ifdef WITH_SSE + { "32bpp-sse4-anim", 32, 32, 8, 32 }, +#endif + { "8bpp-optimized", 8, 8, 8, 8 }, + { "32bpp-anim", 8, 32, 8, 32 }, + }; + + const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName(); + + for (uint i = 0; i < lengthof(replacement_blitters); i++) { + if (!IsInsideMM(depth_wanted_by_base, replacement_blitters[i].min_base_depth, replacement_blitters[i].max_base_depth + 1)) continue; + if (!IsInsideMM(depth_wanted_by_grf, replacement_blitters[i].min_grf_depth, replacement_blitters[i].max_grf_depth + 1)) continue; + const char *repl_blitter = replacement_blitters[i].name; + + if (strcmp(repl_blitter, cur_blitter) == 0) return; + if (BlitterFactory::GetBlitterFactory(repl_blitter) == NULL) continue; + + DEBUG(misc, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter); + Blitter *new_blitter = BlitterFactory::SelectBlitter(repl_blitter); + if (new_blitter == NULL) NOT_REACHED(); + DEBUG(misc, 1, "Successfully switched to %s.", repl_blitter); + break; + } + + if (!_video_driver->AfterBlitterChange()) { + /* Failed to switch blitter, let's hope we can return to the old one. */ + if (BlitterFactory::SelectBlitter(cur_blitter) == NULL || !_video_driver->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config"); } }