Add: Overlay cargo icon in vehicle/depot list when holding shift+ctrl. (#12938)
[openttd-github.git] / src / blitter / factory.hpp
blob5071a168ae1dff129f5da07b37c2ff34bb3fbf6e
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 */
8 /** @file factory.hpp Factory to 'query' all available blitters. */
10 #ifndef BLITTER_FACTORY_HPP
11 #define BLITTER_FACTORY_HPP
13 #include "base.hpp"
14 #include "../debug.h"
15 #include "../string_func.h"
18 /**
19 * The base factory, keeping track of all blitters.
21 class BlitterFactory {
22 private:
23 const std::string name; ///< The name of the blitter factory.
24 const std::string description; ///< The description of the blitter.
26 typedef std::map<std::string, BlitterFactory *> Blitters; ///< Map of blitter factories.
28 /**
29 * Get the map with currently known blitters.
30 * @return The known blitters.
32 static Blitters &GetBlitters()
34 static Blitters &s_blitters = *new Blitters();
35 return s_blitters;
38 /**
39 * Get the currently active blitter.
40 * @return The currently active blitter.
42 static Blitter **GetActiveBlitter()
44 static Blitter *s_blitter = nullptr;
45 return &s_blitter;
48 protected:
49 /**
50 * Construct the blitter, and register it.
51 * @param name The name of the blitter.
52 * @param description A longer description for the blitter.
53 * @param usable Whether the blitter is usable (on the current computer). For example for disabling SSE blitters when the CPU can't handle them.
54 * @pre name != nullptr.
55 * @pre description != nullptr.
56 * @pre There is no blitter registered with this name.
58 BlitterFactory(const char *name, const char *description, bool usable = true) :
59 name(name), description(description)
61 if (usable) {
62 Blitters &blitters = GetBlitters();
63 assert(blitters.find(this->name) == blitters.end());
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.
69 blitters.insert(Blitters::value_type(this->name, this));
70 } else {
71 Debug(driver, 1, "Not registering blitter {} as it is not usable", name);
75 /**
76 * Is the blitter usable with the current drivers and hardware config?
77 * @return True if the blitter can be instantiated.
79 virtual bool IsUsable() const
81 return true;
84 public:
85 virtual ~BlitterFactory()
87 GetBlitters().erase(this->name);
88 if (GetBlitters().empty()) delete &GetBlitters();
91 /**
92 * Find the requested blitter and return its class.
93 * @param name the blitter to select.
94 * @post Sets the blitter so GetCurrentBlitter() returns it too.
96 static Blitter *SelectBlitter(const std::string_view name)
98 BlitterFactory *b = GetBlitterFactory(name);
99 if (b == nullptr) return nullptr;
101 Blitter *newb = b->CreateInstance();
102 delete *GetActiveBlitter();
103 *GetActiveBlitter() = newb;
105 Debug(driver, 1, "Successfully {} blitter '{}'", name.empty() ? "probed" : "loaded", newb->GetName());
106 return newb;
110 * Get the blitter factory with the given name.
111 * @param name the blitter factory to select.
112 * @return The blitter factory, or nullptr when there isn't one with the wanted name.
114 static BlitterFactory *GetBlitterFactory(const std::string_view name)
116 #if defined(DEDICATED)
117 const std::string_view default_blitter = "null";
118 #elif defined(WITH_COCOA)
119 const std::string_view default_blitter = "32bpp-anim";
120 #else
121 const std::string_view default_blitter = "8bpp-optimized";
122 #endif
123 if (GetBlitters().empty()) return nullptr;
124 const std::string_view bname = name.empty() ? default_blitter : name;
126 for (auto &it : GetBlitters()) {
127 BlitterFactory *b = it.second;
128 if (StrEqualsIgnoreCase(bname, b->name)) {
129 return b->IsUsable() ? b : nullptr;
132 return nullptr;
136 * Get the current active blitter (always set by calling SelectBlitter).
138 static Blitter *GetCurrentBlitter()
140 return *GetActiveBlitter();
144 * Fill a buffer with information about the blitters.
145 * @param p The buffer to fill.
146 * @param last The last element of the buffer.
147 * @return p The location till where we filled the buffer.
149 static void GetBlittersInfo(std::back_insert_iterator<std::string> &output_iterator)
151 fmt::format_to(output_iterator, "List of blitters:\n");
152 for (auto &it : GetBlitters()) {
153 BlitterFactory *b = it.second;
154 fmt::format_to(output_iterator, "{:>18}: {}\n", b->name, b->GetDescription());
156 fmt::format_to(output_iterator, "\n");
160 * Get the long, human readable, name for the Blitter-class.
162 std::string_view GetName() const
164 return this->name;
168 * Get a nice description of the blitter-class.
170 std::string_view GetDescription() const
172 return this->description;
176 * Create an instance of this Blitter-class.
178 virtual Blitter *CreateInstance() = 0;
181 extern std::string _ini_blitter;
182 extern bool _blitter_autodetected;
184 #endif /* BLITTER_FACTORY_HPP */