* Check blitter needed by NewGRF config and switch if needed. * @return False when nothing changed, true otherwise. */
| 255 | * @return False when nothing changed, true otherwise. |
| 256 | */ |
| 257 | static bool SwitchNewGRFBlitter() |
| 258 | { |
| 259 | /* Never switch if the blitter was specified by the user. */ |
| 260 | if (!_blitter_autodetected) return false; |
| 261 | |
| 262 | /* Null driver => dedicated server => do nothing. */ |
| 263 | if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return false; |
| 264 | |
| 265 | /* Get preferred depth. |
| 266 | * - depth_wanted_by_base: Depth required by the baseset, i.e. the majority of the sprites. |
| 267 | * - depth_wanted_by_grf: Depth required by some NewGRF. |
| 268 | * Both can force using a 32bpp blitter. depth_wanted_by_base is used to select |
| 269 | * between multiple 32bpp blitters, which perform differently with 8bpp sprites. |
| 270 | */ |
| 271 | uint depth_wanted_by_base = BaseGraphics::GetUsedSet()->blitter == BLT_32BPP ? 32 : 8; |
| 272 | uint depth_wanted_by_grf = _support8bpp != S8BPP_NONE ? 8 : 32; |
| 273 | for (const auto &c : _grfconfig) { |
| 274 | if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND || c->flags.Test(GRFConfigFlag::InitOnly)) continue; |
| 275 | if (c->palette & GRFP_BLT_32BPP) depth_wanted_by_grf = 32; |
| 276 | } |
| 277 | /* We need a 32bpp blitter for font anti-alias. */ |
| 278 | if (GetFontAAState()) depth_wanted_by_grf = 32; |
| 279 | |
| 280 | /* Search the best blitter. */ |
| 281 | static const struct { |
| 282 | const std::string_view name; |
| 283 | uint animation; ///< 0: no support, 1: do support, 2: both |
| 284 | uint min_base_depth, max_base_depth, min_grf_depth, max_grf_depth; |
| 285 | } replacement_blitters[] = { |
| 286 | { "8bpp-optimized", 2, 8, 8, 8, 8 }, |
| 287 | { "40bpp-anim", 2, 8, 32, 8, 32 }, |
| 288 | #ifdef WITH_SSE |
| 289 | { "32bpp-sse4", 0, 32, 32, 8, 32 }, |
| 290 | { "32bpp-ssse3", 0, 32, 32, 8, 32 }, |
| 291 | { "32bpp-sse2", 0, 32, 32, 8, 32 }, |
| 292 | { "32bpp-sse4-anim", 1, 32, 32, 8, 32 }, |
| 293 | #endif |
| 294 | { "32bpp-optimized", 0, 8, 32, 8, 32 }, |
| 295 | #ifdef WITH_SSE |
| 296 | { "32bpp-sse2-anim", 1, 8, 32, 8, 32 }, |
| 297 | #endif |
| 298 | { "32bpp-anim", 1, 8, 32, 8, 32 }, |
| 299 | }; |
| 300 | |
| 301 | const bool animation_wanted = HasBit(_display_opt, DO_FULL_ANIMATION); |
| 302 | std::string_view cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName(); |
| 303 | |
| 304 | for (const auto &replacement_blitter : replacement_blitters) { |
| 305 | if (animation_wanted && (replacement_blitter.animation == 0)) continue; |
| 306 | if (!animation_wanted && (replacement_blitter.animation == 1)) continue; |
| 307 | |
| 308 | if (!IsInsideMM(depth_wanted_by_base, replacement_blitter.min_base_depth, replacement_blitter.max_base_depth + 1)) continue; |
| 309 | if (!IsInsideMM(depth_wanted_by_grf, replacement_blitter.min_grf_depth, replacement_blitter.max_grf_depth + 1)) continue; |
| 310 | |
| 311 | if (replacement_blitter.name == cur_blitter) { |
| 312 | return false; |
| 313 | } |
| 314 | if (BlitterFactory::GetBlitterFactory(replacement_blitter.name) == nullptr) continue; |
no test coverage detected