openMSX
Display.cc
Go to the documentation of this file.
1 #include "Display.hh"
2 #include "RendererFactory.hh"
3 #include "Layer.hh"
4 #include "VideoSystem.hh"
5 #include "VideoLayer.hh"
6 #include "EventDistributor.hh"
7 #include "FinishFrameEvent.hh"
8 #include "FileOperations.hh"
9 #include "FileContext.hh"
10 #include "InputEvents.hh"
11 #include "CliComm.hh"
12 #include "Timer.hh"
13 #include "BooleanSetting.hh"
14 #include "IntegerSetting.hh"
15 #include "EnumSetting.hh"
16 #include "Reactor.hh"
17 #include "MSXMotherBoard.hh"
18 #include "HardwareConfig.hh"
19 #include "TclArgParser.hh"
20 #include "XMLElement.hh"
22 #include "CommandException.hh"
23 #include "StringOp.hh"
24 #include "Version.hh"
25 #include "build-info.hh"
26 #include "checked_cast.hh"
27 #include "outer.hh"
28 #include "ranges.hh"
29 #include "stl.hh"
30 #include "unreachable.hh"
31 #include "view.hh"
32 #include "xrange.hh"
33 #include <cassert>
34 
35 using std::string;
36 using std::vector;
37 
38 namespace openmsx {
39 
41  : RTSchedulable(reactor_.getRTScheduler())
42  , screenShotCmd(reactor_.getCommandController())
43  , fpsInfo(reactor_.getOpenMSXInfoCommand())
44  , osdGui(reactor_.getCommandController(), *this)
45  , reactor(reactor_)
46  , renderSettings(reactor.getCommandController())
47  , commandConsole(reactor.getGlobalCommandController(),
48  reactor.getEventDistributor(), *this)
49  , currentRenderer(RenderSettings::UNINITIALIZED)
50  , switchInProgress(false)
51 {
52  frameDurationSum = 0;
53  repeat(NUM_FRAME_DURATIONS, [&] {
54  frameDurations.addFront(20);
55  frameDurationSum += 20;
56  });
57  prevTimeStamp = Timer::getTime();
58 
59  EventDistributor& eventDistributor = reactor.getEventDistributor();
61  *this);
63  *this);
65  *this);
67  *this);
68 #if PLATFORM_ANDROID
70  *this);
71 #endif
72  renderSettings.getRendererSetting().attach(*this);
73  renderSettings.getFullScreenSetting().attach(*this);
74  renderSettings.getScaleFactorSetting().attach(*this);
75  renderFrozen = false;
76 }
77 
79 {
80  renderSettings.getRendererSetting().detach(*this);
81  renderSettings.getFullScreenSetting().detach(*this);
82  renderSettings.getScaleFactorSetting().detach(*this);
83 
84  EventDistributor& eventDistributor = reactor.getEventDistributor();
85 #if PLATFORM_ANDROID
87  *this);
88 #endif
90  *this);
92  *this);
94  *this);
96  *this);
97 
98  resetVideoSystem();
99 
100  assert(listeners.empty());
101 }
102 
104 {
105  assert(!videoSystem);
106  assert(currentRenderer == RenderSettings::UNINITIALIZED);
107  assert(!switchInProgress);
108  currentRenderer = renderSettings.getRenderer();
109  switchInProgress = true;
110  doRendererSwitch();
111 }
112 
114 {
115  assert(videoSystem);
116  return *videoSystem;
117 }
118 
120 {
121  return videoSystem ? videoSystem->getOutputSurface() : nullptr;
122 }
123 
124 void Display::resetVideoSystem()
125 {
126  videoSystem.reset();
127  // At this point all layers except for the Video9000 layer
128  // should be gone.
129  //assert(layers.empty());
130 }
131 
133 {
134  return reactor.getCliComm();
135 }
136 
138 {
139  assert(!contains(listeners, &listener));
140  listeners.push_back(&listener);
141 }
142 
144 {
145  move_pop_back(listeners, rfind_unguarded(listeners, &listener));
146 }
147 
149 {
150  for (auto* l : layers) {
151  if (l->getZ() == Layer::Z_MSX_ACTIVE) {
152  return l;
153  }
154  }
155  return nullptr;
156 }
157 
158 Display::Layers::iterator Display::baseLayer()
159 {
160  // Note: It is possible to cache this, but since the number of layers is
161  // low at the moment, it's not really worth it.
162  auto it = end(layers);
163  while (true) {
164  if (it == begin(layers)) {
165  // There should always be at least one opaque layer.
166  // TODO: This is not true for DummyVideoSystem.
167  // Anyway, a missing layer will probably stand out visually,
168  // so do we really have to assert on it?
169  //UNREACHABLE;
170  return it;
171  }
172  --it;
173  if ((*it)->getCoverage() == Layer::COVER_FULL) return it;
174  }
175 }
176 
177 void Display::executeRT()
178 {
179  videoSystem->repaint();
180 }
181 
182 int Display::signalEvent(const std::shared_ptr<const Event>& event)
183 {
184  if (event->getType() == OPENMSX_FINISH_FRAME_EVENT) {
185  const auto& ffe = checked_cast<const FinishFrameEvent&>(*event);
186  if (ffe.needRender()) {
187  videoSystem->repaint();
189  std::make_shared<SimpleEvent>(
191  }
192  } else if (event->getType() == OPENMSX_SWITCH_RENDERER_EVENT) {
193  doRendererSwitch();
194  } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) {
195  videoSystem->updateWindowTitle();
196  } else if (event->getType() == OPENMSX_EXPOSE_EVENT) {
197  // Don't render too often, and certainly not when the screen
198  // will anyway soon be rendered.
199  repaintDelayed(100 * 1000); // 10fps
200  } else if (PLATFORM_ANDROID && event->getType() == OPENMSX_FOCUS_EVENT) {
201  // On Android, the rendering must be frozen when the app is sent to
202  // the background, because Android takes away all graphics resources
203  // from the app. It simply destroys the entire graphics context.
204  // Though, a repaint() must happen within the focus-lost event
205  // so that the SDL Android port realizes that the graphics context
206  // is gone and will re-build it again on the first flush to the
207  // surface after the focus has been regained.
208 
209  // Perform a repaint before updating the renderFrozen flag:
210  // -When loosing the focus, this repaint will flush a last
211  // time the SDL surface, making sure that the Android SDL
212  // port discovers that the graphics context is gone.
213  // -When gaining the focus, this repaint does nothing as
214  // the renderFrozen flag is still false
215  videoSystem->repaint();
216  const auto& focusEvent = checked_cast<const FocusEvent&>(*event);
217  ad_printf("Setting renderFrozen to %d", !focusEvent.getGain());
218  renderFrozen = !focusEvent.getGain();
219  }
220  return 0;
221 }
222 
224 {
225  string title = Version::full();
226  if (!Version::RELEASE) {
227  strAppend(title, " [", BUILD_FLAVOUR, ']');
228  }
229  if (MSXMotherBoard* motherboard = reactor.getMotherBoard()) {
230  if (const HardwareConfig* machine = motherboard->getMachineConfig()) {
231  const XMLElement& config = machine->getConfig();
232  strAppend(title, " - ",
233  config.getChild("info").getChildData("manufacturer"), ' ',
234  config.getChild("info").getChildData("code"));
235  }
236  }
237  return title;
238 }
239 
240 void Display::update(const Setting& setting)
241 {
242  if (&setting == &renderSettings.getRendererSetting()) {
243  checkRendererSwitch();
244  } else if (&setting == &renderSettings.getFullScreenSetting()) {
245  checkRendererSwitch();
246  } else if (&setting == &renderSettings.getScaleFactorSetting()) {
247  checkRendererSwitch();
248  } else {
249  UNREACHABLE;
250  }
251 }
252 
253 void Display::checkRendererSwitch()
254 {
255  if (switchInProgress) {
256  // This method only queues a request to switch renderer (see
257  // comments below why). If there already is such a request
258  // queued we don't need to do it again.
259  return;
260  }
261  auto newRenderer = renderSettings.getRenderer();
262  if ((newRenderer != currentRenderer) ||
263  !getVideoSystem().checkSettings()) {
264  currentRenderer = newRenderer;
265  // don't do the actual switching in the Tcl callback
266  // it seems creating and destroying Settings (= Tcl vars)
267  // causes problems???
268  switchInProgress = true;
270  std::make_shared<SimpleEvent>(
272  }
273 }
274 
275 void Display::doRendererSwitch()
276 {
277  assert(switchInProgress);
278 
279  bool success = false;
280  while (!success) {
281  try {
282  doRendererSwitch2();
283  success = true;
284  } catch (MSXException& e) {
285  auto& rendererSetting = renderSettings.getRendererSetting();
286  string errorMsg = strCat(
287  "Couldn't activate renderer ",
288  rendererSetting.getString(),
289  ": ", e.getMessage());
290  // now try some things that might work against this:
291  if (rendererSetting.getEnum() != RenderSettings::SDL) {
292  errorMsg += "\nTrying to switch to SDL renderer instead...";
293  rendererSetting.setEnum(RenderSettings::SDL);
294  currentRenderer = RenderSettings::SDL;
295  } else {
296  auto& scaleFactorSetting = renderSettings.getScaleFactorSetting();
297  unsigned curval = scaleFactorSetting.getInt();
298  if (curval == 1) {
299  throw MSXException(
300  e.getMessage(),
301  " (and I have no other ideas to try...)"); // give up and die... :(
302  }
303  strAppend(errorMsg, "\nTrying to decrease scale_factor setting from ",
304  curval, " to ", curval - 1, "...");
305  scaleFactorSetting.setInt(curval - 1);
306  }
307  getCliComm().printWarning(errorMsg);
308  }
309  }
310 
311  switchInProgress = false;
312 }
313 
314 void Display::doRendererSwitch2()
315 {
316  for (auto& l : listeners) {
317  l->preVideoSystemChange();
318  }
319 
320  resetVideoSystem();
321  videoSystem = RendererFactory::createVideoSystem(reactor);
322 
323  for (auto& l : listeners) {
324  l->postVideoSystemChange();
325  }
326 }
327 
329 {
330  if (switchInProgress) {
331  // The checkRendererSwitch() method will queue a
332  // SWITCH_RENDERER_EVENT, but before that event is handled
333  // we shouldn't do any repaints (with inconsistent setting
334  // values and render objects). This can happen when this
335  // method gets called because of a DELAYED_REPAINT_EVENT
336  // (DELAYED_REPAINT_EVENT was already queued before
337  // SWITCH_RENDERER_EVENT is queued).
338  return;
339  }
340 
341  cancelRT(); // cancel delayed repaint
342 
343  if (!renderFrozen) {
344  assert(videoSystem);
345  if (OutputSurface* surface = videoSystem->getOutputSurface()) {
346  repaint(*surface);
347  videoSystem->flush();
348  }
349  }
350 
351  // update fps statistics
352  auto now = Timer::getTime();
353  auto duration = now - prevTimeStamp;
354  prevTimeStamp = now;
355  frameDurationSum += duration - frameDurations.removeBack();
356  frameDurations.addFront(duration);
357 }
358 
360 {
361  for (auto it = baseLayer(); it != end(layers); ++it) {
362  if ((*it)->getCoverage() != Layer::COVER_NONE) {
363  (*it)->paint(surface);
364  }
365  }
366 }
367 
368 void Display::repaintDelayed(uint64_t delta)
369 {
370  if (isPendingRT()) {
371  // already a pending repaint
372  return;
373  }
374  scheduleRT(unsigned(delta));
375 }
376 
378 {
379  int z = layer.getZ();
380  auto it = ranges::find_if(layers, [&](Layer* l) { return l->getZ() > z; });
381  layers.insert(it, &layer);
382  layer.setDisplay(*this);
383 }
384 
386 {
387  layers.erase(rfind_unguarded(layers, &layer));
388 }
389 
390 void Display::updateZ(Layer& layer)
391 {
392  // Remove at old Z-index...
393  removeLayer(layer);
394  // ...and re-insert at new Z-index.
395  addLayer(layer);
396 }
397 
398 
399 // ScreenShotCmd
400 
401 Display::ScreenShotCmd::ScreenShotCmd(CommandController& commandController_)
402  : Command(commandController_, "screenshot")
403 {
404 }
405 
406 void Display::ScreenShotCmd::execute(span<const TclObject> tokens, TclObject& result)
407 {
408  std::string_view prefix = "openmsx";
409  bool rawShot = false;
410  bool msxOnly = false;
411  bool doubleSize = false;
412  bool withOsd = false;
413  ArgsInfo info[] = {
414  valueArg("-prefix", prefix),
415  flagArg("-raw", rawShot),
416  flagArg("-msxonly", msxOnly),
417  flagArg("-doublesize", doubleSize),
418  flagArg("-with-osd", withOsd)
419  };
420  auto arguments = parseTclArgs(getInterpreter(), tokens.subspan(1), info);
421 
422  auto& display = OUTER(Display, screenShotCmd);
423  if (msxOnly) {
424  display.getCliComm().printWarning(
425  "The -msxonly option has been deprecated and will "
426  "be removed in a future release. Instead, use the "
427  "-raw option for the same effect.");
428  rawShot = true;
429  }
430  if (doubleSize && !rawShot) {
431  throw CommandException("-doublesize option can only be used in "
432  "combination with -raw");
433  }
434  if (rawShot && withOsd) {
435  throw CommandException("-with-osd cannot be used in "
436  "combination with -raw");
437  }
438 
439  std::string_view fname;
440  switch (arguments.size()) {
441  case 0:
442  // nothing
443  break;
444  case 1:
445  fname = arguments[0].getString();
446  break;
447  default:
448  throw SyntaxError();
449  }
451  fname, "screenshots", prefix, ".png");
452 
453  if (!rawShot) {
454  // include all layers (OSD stuff, console)
455  try {
456  display.getVideoSystem().takeScreenShot(filename, withOsd);
457  } catch (MSXException& e) {
458  throw CommandException(
459  "Failed to take screenshot: ", e.getMessage());
460  }
461  } else {
462  auto* videoLayer = dynamic_cast<VideoLayer*>(
463  display.findActiveLayer());
464  if (!videoLayer) {
465  throw CommandException(
466  "Current renderer doesn't support taking screenshots.");
467  }
468  unsigned height = doubleSize ? 480 : 240;
469  try {
470  videoLayer->takeRawScreenShot(height, filename);
471  } catch (MSXException& e) {
472  throw CommandException(
473  "Failed to take screenshot: ", e.getMessage());
474  }
475  }
476 
477  display.getCliComm().printInfo("Screen saved to ", filename);
478  result = filename;
479 }
480 
481 string Display::ScreenShotCmd::help(const vector<string>& /*tokens*/) const
482 {
483  // Note: -no-sprites option is implemented in Tcl
484  return "screenshot Write screenshot to file \"openmsxNNNN.png\"\n"
485  "screenshot <filename> Write screenshot to indicated file\n"
486  "screenshot -prefix foo Write screenshot to file \"fooNNNN.png\"\n"
487  "screenshot -raw 320x240 raw screenshot (of MSX screen only)\n"
488  "screenshot -raw -doublesize 640x480 raw screenshot (of MSX screen only)\n"
489  "screenshot -with-osd Include OSD elements in the screenshot\n"
490  "screenshot -no-sprites Don't include sprites in the screenshot\n";
491 }
492 
493 void Display::ScreenShotCmd::tabCompletion(vector<string>& tokens) const
494 {
495  static constexpr const char* const extra[] = {
496  "-prefix", "-raw", "-doublesize", "-with-osd", "-no-sprites",
497  };
498  completeFileName(tokens, userFileContext(), extra);
499 }
500 
501 
502 // FpsInfoTopic
503 
504 Display::FpsInfoTopic::FpsInfoTopic(InfoCommand& openMSXInfoCommand)
505  : InfoTopic(openMSXInfoCommand, "fps")
506 {
507 }
508 
509 void Display::FpsInfoTopic::execute(span<const TclObject> /*tokens*/,
510  TclObject& result) const
511 {
512  auto& display = OUTER(Display, fpsInfo);
513  result = 1000000.0f * Display::NUM_FRAME_DURATIONS / display.frameDurationSum;
514 }
515 
516 string Display::FpsInfoTopic::help(const vector<string>& /*tokens*/) const
517 {
518  return "Returns the current rendering speed in frames per second.";
519 }
520 
521 } // namespace openmsx
openmsx::CircularBuffer::addFront
void addFront(const T &element)
Definition: CircularBuffer.hh:16
HardwareConfig.hh
VideoSystem.hh
IntegerSetting.hh
contains
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition: stl.hh:92
openmsx::RTSchedulable::isPendingRT
bool isPendingRT() const
Definition: RTSchedulable.cc:27
openmsx::RTSchedulable
Definition: RTSchedulable.hh:11
openmsx::Subject::detach
void detach(Observer< T > &observer)
Definition: Subject.hh:56
Timer.hh
Display.hh
openmsx::RendererFactory::createVideoSystem
unique_ptr< VideoSystem > createVideoSystem(Reactor &reactor)
Create the video system required by the current renderer setting.
Definition: RendererFactory.cc:28
openmsx::RenderSettings
Class containing all settings for renderers.
Definition: RenderSettings.hh:22
openmsx::flagArg
ArgsInfo flagArg(std::string_view name, bool &flag)
Definition: TclArgParser.hh:72
openmsx::Display::~Display
~Display()
Definition: Display.cc:78
openmsx::XMLElement::getChildData
const std::string & getChildData(std::string_view childName) const
Definition: XMLElement.cc:121
openmsx::Display::attach
void attach(VideoSystemChangeListener &listener)
Definition: Display.cc:137
openmsx::Layer::setDisplay
void setDisplay(LayerListener &display_)
Store pointer to Display.
Definition: Layer.hh:59
openmsx::RenderSettings::getScaleFactorSetting
IntegerSetting & getScaleFactorSetting()
The current scaling factor.
Definition: RenderSettings.hh:119
ranges.hh
openmsx::Reactor::getEventDistributor
EventDistributor & getEventDistributor()
Definition: Reactor.hh:81
end
auto end(const zstring_view &x)
Definition: zstring_view.hh:83
openmsx::Timer::getTime
uint64_t getTime()
Get current (real) time in us.
Definition: Timer.cc:7
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:172
XMLElement.hh
openmsx::CircularBuffer::removeBack
T & removeBack()
Definition: CircularBuffer.hh:42
openmsx::VideoSystem
Video back-end system.
Definition: VideoSystem.hh:21
openmsx::Subject::attach
void attach(Observer< T > &observer)
Definition: Subject.hh:50
Layer.hh
openmsx::Display::getOutputSurface
OutputSurface * getOutputSurface()
Definition: Display.cc:119
strAppend
void strAppend(std::string &result, Ts &&...ts)
Definition: strCat.hh:669
RendererFactory.hh
openmsx::Setting
Definition: Setting.hh:127
VideoSystemChangeListener.hh
openmsx::EventDistributor
Definition: EventDistributor.hh:17
BooleanSetting.hh
span::subspan
constexpr subspan_return_t< Offset, Count > subspan() const
Definition: span.hh:266
repeat
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition: xrange.hh:170
openmsx::RenderSettings::getFullScreenSetting
BooleanSetting & getFullScreenSetting()
Full screen [on, off].
Definition: RenderSettings.hh:67
openmsx::OPENMSX_SWITCH_RENDERER_EVENT
@ OPENMSX_SWITCH_RENDERER_EVENT
Definition: Event.hh:48
openmsx::Display::repaintDelayed
void repaintDelayed(uint64_t delta)
Definition: Display.cc:368
Version.hh
span
Definition: span.hh:126
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:67
PLATFORM_ANDROID
#define PLATFORM_ANDROID
Definition: build-info.hh:17
openmsx::IntegerSetting::getInt
int getInt() const noexcept
Definition: IntegerSetting.hh:21
Reactor.hh
openmsx::RTSchedulable::scheduleRT
void scheduleRT(uint64_t delta)
Definition: RTSchedulable.cc:16
TclArgParser.hh
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
move_pop_back
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
Definition: stl.hh:182
openmsx::CliComm::printWarning
void printWarning(std::string_view message)
Definition: CliComm.cc:10
UNREACHABLE
#define UNREACHABLE
Definition: unreachable.hh:38
openmsx::RenderSettings::UNINITIALIZED
@ UNINITIALIZED
Definition: RenderSettings.hh:27
openmsx::RTSchedulable::cancelRT
bool cancelRT()
Definition: RTSchedulable.cc:22
openmsx::Reactor::getMotherBoard
MSXMotherBoard * getMotherBoard() const
Definition: Reactor.cc:372
openmsx::Display::getVideoSystem
VideoSystem & getVideoSystem()
Definition: Display.cc:113
openmsx::XMLElement
Definition: XMLElement.hh:16
begin
auto begin(const zstring_view &x)
Definition: zstring_view.hh:82
openmsx::MSXMotherBoard
Definition: MSXMotherBoard.hh:61
openmsx::OPENMSX_FRAME_DRAWN_EVENT
@ OPENMSX_FRAME_DRAWN_EVENT
Sent when a OPENMSX_FINISH_FRAME_EVENT caused a redraw of the screen.
Definition: Event.hh:45
EventDistributor.hh
openmsx::filename
constexpr const char *const filename
Definition: FirmwareSwitch.cc:10
InputEvents.hh
openmsx::Display::getWindowTitle
std::string getWindowTitle()
Definition: Display.cc:223
openmsx::Layer
Interface for display layers.
Definition: Layer.hh:12
build-info.hh
openmsx::Display::createVideoSystem
void createVideoSystem()
Definition: Display.cc:103
openmsx::FileOperations::parseCommandFileArgument
string parseCommandFileArgument(string_view argument, string_view directory, string_view prefix, string_view extension)
Helper function for parsing filename arguments in Tcl commands.
Definition: FileOperations.cc:604
view.hh
EnumSetting.hh
FinishFrameEvent.hh
FileContext.hh
openmsx::RenderSettings::getRenderer
RendererID getRenderer() const
Definition: RenderSettings.hh:111
openmsx::Display::findActiveLayer
Layer * findActiveLayer() const
Definition: Display.cc:148
openmsx::RenderSettings::SDL
@ SDL
Definition: RenderSettings.hh:27
FileOperations.hh
outer.hh
checked_cast.hh
openmsx::OPENMSX_EXPOSE_EVENT
@ OPENMSX_EXPOSE_EVENT
Send when (part of) the openMSX window gets exposed, and thus should be repainted.
Definition: Event.hh:69
openmsx::OPENMSX_FOCUS_EVENT
@ OPENMSX_FOCUS_EVENT
Definition: Event.hh:29
openmsx::Layer::getZ
ZIndex getZ() const
Query the Z-index of this layer.
Definition: Layer.hh:50
StringOp.hh
openmsx::Reactor::getCliComm
CliComm & getCliComm()
Definition: Reactor.cc:310
VideoLayer.hh
openmsx::OPENMSX_MACHINE_LOADED_EVENT
@ OPENMSX_MACHINE_LOADED_EVENT
Send when a (new) machine configuration is loaded.
Definition: Event.hh:60
openmsx::OutputSurface
A frame buffer where pixels can be written to.
Definition: OutputSurface.hh:20
openmsx::parseTclArgs
std::vector< TclObject > parseTclArgs(Interpreter &interp, span< const TclObject > inArgs, span< const ArgsInfo > table)
Definition: commands/TclArgParser.cc:11
openmsx::CliComm
Definition: CliComm.hh:11
openmsx::Display::repaint
void repaint()
Redraw the display.
Definition: Display.cc:328
ad_printf
#define ad_printf(...)
Definition: openmsx.hh:11
openmsx::Version::full
static std::string full()
Definition: Version.cc:8
openmsx::HardwareConfig
Definition: HardwareConfig.hh:22
stl.hh
ranges::find_if
auto find_if(InputRange &&range, UnaryPredicate pred)
Definition: ranges.hh:113
openmsx::Display::Display
Display(Reactor &reactor)
Definition: Display.cc:40
openmsx::Layer::COVER_FULL
@ COVER_FULL
Layer fully covers the screen: any underlying layers are invisible.
Definition: Layer.hh:32
openmsx::Layer::Z_MSX_ACTIVE
@ Z_MSX_ACTIVE
Definition: Layer.hh:21
openmsx::EventDistributor::registerEventListener
void registerEventListener(EventType type, EventListener &listener, Priority priority=OTHER)
Registers a given object to receive certain events.
Definition: EventDistributor.cc:23
openmsx::valueArg
ArgsInfo valueArg(std::string_view name, T &value)
Definition: TclArgParser.hh:85
openmsx::Display::addLayer
void addLayer(Layer &layer)
Definition: Display.cc:377
unreachable.hh
openmsx::OPENMSX_FINISH_FRAME_EVENT
@ OPENMSX_FINISH_FRAME_EVENT
Sent when VDP (V99x8 or V9990) reaches the end of a frame.
Definition: Event.hh:39
openmsx::Version::RELEASE
static const bool RELEASE
Definition: Version.hh:12
openmsx::Layer::COVER_NONE
@ COVER_NONE
Layer is not visible, that is completely transparent.
Definition: Layer.hh:39
CliComm.hh
openmsx::EventDistributor::unregisterEventListener
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
Definition: EventDistributor.cc:35
openmsx::Display::getCliComm
CliComm & getCliComm() const
Definition: Display.cc:132
openmsx::VideoSystemChangeListener
Definition: VideoSystemChangeListener.hh:7
strCat
std::string strCat(Ts &&...ts)
Definition: strCat.hh:591
CommandException.hh
rfind_unguarded
auto rfind_unguarded(RANGE &range, const VAL &val)
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
Definition: stl.hh:157
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
MSXMotherBoard.hh
xrange.hh
openmsx::Display::removeLayer
void removeLayer(Layer &layer)
Definition: Display.cc:385
openmsx::XMLElement::getChild
const XMLElement & getChild(std::string_view childName) const
Definition: XMLElement.cc:116
openmsx::EventDistributor::distributeEvent
void distributeEvent(const EventPtr &event)
Schedule the given event for delivery.
Definition: EventDistributor.cc:44
openmsx::Display::detach
void detach(VideoSystemChangeListener &listener)
Definition: Display.cc:143
openmsx::RenderSettings::getRendererSetting
RendererSetting & getRendererSetting()
The current renderer.
Definition: RenderSettings.hh:110