OpenTTD Source 20250524-master-gc366e6a48e
factory.hpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef BLITTER_FACTORY_HPP
11#define BLITTER_FACTORY_HPP
12
13#include "base.hpp"
14#include "../debug.h"
15#include "../string_func.h"
16
17
22private:
23 const std::string name;
24 const std::string description;
25
26 typedef std::map<std::string, BlitterFactory *> Blitters;
27
33 {
34 static Blitters &s_blitters = *new Blitters();
35 return s_blitters;
36 }
37
42 static std::unique_ptr<Blitter> &GetActiveBlitter()
43 {
44 static std::unique_ptr<Blitter> s_blitter = nullptr;
45 return s_blitter;
46 }
47
48protected:
58 BlitterFactory(std::string_view name, std::string_view description, bool usable = true) :
60 {
61 if (usable) {
62 Blitters &blitters = GetBlitters();
63 assert(blitters.find(this->name) == blitters.end());
64 /*
65 * Only add when the blitter is usable. Do not bail out or
66 * do more special things since the blitters are always
67 * instantiated upon start anyhow and freed upon shutdown.
68 */
69 blitters.insert(Blitters::value_type(this->name, this));
70 } else {
71 Debug(driver, 1, "Not registering blitter {} as it is not usable", name);
72 }
73 }
74
79 virtual bool IsUsable() const
80 {
81 return true;
82 }
83
84public:
85 virtual ~BlitterFactory()
86 {
87 GetBlitters().erase(this->name);
88 if (GetBlitters().empty()) delete &GetBlitters();
89 }
90
96 static Blitter *SelectBlitter(std::string_view name)
97 {
99 if (b == nullptr) return nullptr;
100
102
103 Debug(driver, 1, "Successfully {} blitter '{}'", name.empty() ? "probed" : "loaded", GetCurrentBlitter()->GetName());
104 return GetCurrentBlitter();
105 }
106
112 static BlitterFactory *GetBlitterFactory(std::string_view name)
113 {
114#if defined(DEDICATED)
115 static const std::string_view default_blitter = "null";
116#elif defined(WITH_COCOA)
117 static const std::string_view default_blitter = "32bpp-anim";
118#else
119 static const std::string_view default_blitter = "8bpp-optimized";
120#endif
121 if (GetBlitters().empty()) return nullptr;
122 std::string_view bname = name.empty() ? default_blitter : name;
123
124 for (auto &it : GetBlitters()) {
125 BlitterFactory *b = it.second;
126 if (StrEqualsIgnoreCase(bname, b->name)) {
127 return b->IsUsable() ? b : nullptr;
128 }
129 }
130 return nullptr;
131 }
132
137 {
138 return GetActiveBlitter().get();
139 }
140
147 static void GetBlittersInfo(std::back_insert_iterator<std::string> &output_iterator)
148 {
149 fmt::format_to(output_iterator, "List of blitters:\n");
150 for (auto &it : GetBlitters()) {
151 BlitterFactory *b = it.second;
152 fmt::format_to(output_iterator, "{:>18}: {}\n", b->name, b->GetDescription());
153 }
154 fmt::format_to(output_iterator, "\n");
155 }
156
160 std::string_view GetName() const
161 {
162 return this->name;
163 }
164
168 std::string_view GetDescription() const
169 {
170 return this->description;
171 }
172
176 virtual std::unique_ptr<Blitter> CreateInstance() = 0;
177};
178
179extern std::string _ini_blitter;
180extern bool _blitter_autodetected;
181
182#endif /* BLITTER_FACTORY_HPP */
Base for all blitters.
The base factory, keeping track of all blitters.
Definition factory.hpp:21
std::string_view GetName() const
Get the long, human readable, name for the Blitter-class.
Definition factory.hpp:160
static BlitterFactory * GetBlitterFactory(std::string_view name)
Get the blitter factory with the given name.
Definition factory.hpp:112
virtual std::unique_ptr< Blitter > CreateInstance()=0
Create an instance of this Blitter-class.
virtual bool IsUsable() const
Is the blitter usable with the current drivers and hardware config?
Definition factory.hpp:79
const std::string description
The description of the blitter.
Definition factory.hpp:24
std::map< std::string, BlitterFactory * > Blitters
Map of blitter factories.
Definition factory.hpp:26
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:136
static Blitters & GetBlitters()
Get the map with currently known blitters.
Definition factory.hpp:32
static void GetBlittersInfo(std::back_insert_iterator< std::string > &output_iterator)
Fill a buffer with information about the blitters.
Definition factory.hpp:147
static Blitter * SelectBlitter(std::string_view name)
Find the requested blitter and return its class.
Definition factory.hpp:96
BlitterFactory(std::string_view name, std::string_view description, bool usable=true)
Construct the blitter, and register it.
Definition factory.hpp:58
const std::string name
The name of the blitter factory.
Definition factory.hpp:23
static std::unique_ptr< Blitter > & GetActiveBlitter()
Get the currently active blitter.
Definition factory.hpp:42
std::string_view GetDescription() const
Get a nice description of the blitter-class.
Definition factory.hpp:168
How all blitters should look like.
Definition base.hpp:29
virtual std::string_view GetName()=0
Get the name of the blitter, the same as the Factory-instance returns.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
bool _blitter_autodetected
Was the blitter autodetected or specified by the user?
Definition driver.cpp:37
std::string _ini_blitter
The blitter as stored in the configuration file.
Definition driver.cpp:36
bool StrEqualsIgnoreCase(std::string_view str1, std::string_view str2)
Compares two string( view)s for equality, while ignoring the case of the characters.
Definition string.cpp:321