44 , screenShotCmd(reactor_.getCommandController())
45 , fpsInfo(reactor_.getOpenMSXInfoCommand())
46 , osdGui(reactor_.getCommandController(), *this)
48 , renderSettings(reactor.getCommandController())
51 repeat(NUM_FRAME_DURATIONS, [&] {
53 frameDurationSum += 20;
78 assert(listeners.empty());
85 assert(!switchInProgress);
87 switchInProgress =
true;
99 return videoSystem ? videoSystem->getOutputSurface() :
nullptr;
102void Display::resetVideoSystem()
117 assert(!
contains(listeners, &listener));
118 listeners.push_back(&listener);
129 return (it != layers.end()) ? *it :
nullptr;
132Display::Layers::iterator Display::baseLayer()
136 auto it =
end(layers);
138 if (it ==
begin(layers)) {
151void Display::executeRT()
156bool Display::signalEvent(
const Event& event)
159 [&](
const FinishFrameEvent&
e) {
160 if (
e.needRender()) {
165 [&](
const SwitchRendererEvent& ) {
168 [&](
const MachineLoadedEvent& ) {
169 videoSystem->updateWindowTitle();
171 [&](
const WindowEvent&
e) {
172 const auto& evt =
e.getSdlWindowEvent();
173 if (evt.event == SDL_WINDOWEVENT_EXPOSED) {
179 evt.event ==
one_of(SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_FOCUS_LOST)) {
195 bool lost = evt.event == SDL_WINDOWEVENT_FOCUS_LOST;
196 ad_printf(
"Setting renderFrozen to %d", lost);
200 [](
const EventBase&) { }
209 strAppend(title,
" [", BUILD_FLAVOUR,
']');
212 if (
const HardwareConfig* machine = motherboard->getMachineConfig()) {
213 const auto& config = machine->getConfig();
215 config.getChild(
"info").getChildData(
"manufacturer"),
' ',
216 config.getChild(
"info").getChildData(
"code"));
224 if (
auto pos = videoSystem->getWindowPosition()) {
233 videoSystem->setWindowPosition(pos);
248 return 1000000.0f * NUM_FRAME_DURATIONS / narrow_cast<float>(frameDurationSum);
253 assert(&
setting == &renderSettings.getRendererSetting());
254 checkRendererSwitch();
257void Display::checkRendererSwitch()
259 if (switchInProgress) {
266 if (newRenderer != currentRenderer) {
267 currentRenderer = newRenderer;
271 switchInProgress =
true;
276void Display::doRendererSwitch()
278 assert(switchInProgress);
280 bool success =
false;
285 }
catch (MSXException& e) {
288 "Couldn't activate renderer ",
289 rendererSetting.getString(),
290 ": ",
e.getMessage());
293 auto curVal = scaleFactorSetting.
getInt();
297 " (and I have no other ideas to try...)");
299 strAppend(errorMsg,
"\nTrying to decrease scale_factor setting from ",
300 curVal,
" to ", curVal - 1,
"...");
301 scaleFactorSetting.setInt(curVal - 1);
306 switchInProgress =
false;
309void Display::doRendererSwitch2()
311 for (
auto& l : listeners) {
312 l->preVideoSystemChange();
318 for (
auto& l : listeners) {
319 l->postVideoSystemChange();
325 if (switchInProgress) {
340 if (
OutputSurface* surface = videoSystem->getOutputSurface()) {
342 videoSystem->flush();
348 auto duration = now - prevTimeStamp;
350 frameDurationSum += duration - frameDurations.
removeBack();
360 for (
auto it = baseLayer(); it !=
end(layers); ++it) {
362 (*it)->paint(surface);
371 videoSystem->repaint();
385 auto z = layer.
getZ();
387 layers.insert(it, &layer);
396void Display::updateZ(
Layer& layer)
noexcept
407Display::ScreenShotCmd::ScreenShotCmd(CommandController& commandController_)
408 : Command(commandController_,
"screenshot")
412void Display::ScreenShotCmd::execute(std::span<const TclObject> tokens, TclObject& result)
414 std::string_view prefix =
"openmsx";
415 bool rawShot =
false;
416 bool msxOnly =
false;
417 bool doubleSize =
false;
418 bool withOsd =
false;
423 flagArg(
"-doublesize", doubleSize),
426 auto arguments =
parseTclArgs(getInterpreter(), tokens.subspan(1), info);
428 auto& display =
OUTER(Display, screenShotCmd);
430 display.getCliComm().printWarning(
431 "The -msxonly option has been deprecated and will "
432 "be removed in a future release. Instead, use the "
433 "-raw option for the same effect.");
436 if (doubleSize && !rawShot) {
437 throw CommandException(
"-doublesize option can only be used in "
438 "combination with -raw");
440 if (rawShot && withOsd) {
441 throw CommandException(
"-with-osd cannot be used in "
442 "combination with -raw");
445 std::string_view fname;
446 switch (arguments.size()) {
451 fname = arguments[0].getString();
457 fname, SCREENSHOT_DIR, prefix, SCREENSHOT_EXTENSION);
462 display.getVideoSystem().takeScreenShot(filename, withOsd);
463 }
catch (MSXException& e) {
464 throw CommandException(
465 "Failed to take screenshot: ",
e.getMessage());
468 auto* videoLayer =
dynamic_cast<VideoLayer*
>(
469 display.findActiveLayer());
471 throw CommandException(
472 "Current renderer doesn't support taking screenshots.");
474 unsigned height = doubleSize ? 480 : 240;
476 videoLayer->takeRawScreenShot(height, filename);
477 }
catch (MSXException& e) {
478 throw CommandException(
479 "Failed to take screenshot: ",
e.getMessage());
483 display.getCliComm().printInfo(
"Screen saved to ", filename);
487string Display::ScreenShotCmd::help(std::span<const TclObject> )
const
492 return "screenshot Write screenshot to file \"openmsxNNNN.png\"\n"
493 "screenshot <filename> Write screenshot to indicated file\n"
494 "screenshot -prefix foo Write screenshot to file \"fooNNNN.png\"\n"
495 "screenshot -raw 320x240 raw screenshot (of MSX screen only)\n"
496 "screenshot -raw -doublesize 640x480 raw screenshot (of MSX screen only)\n"
497 "screenshot -with-osd Include OSD elements in the screenshot\n"
498 "screenshot -no-sprites Don't include sprites in the screenshot\n"
499 "screenshot -guess-name Guess the name of the running software and use it as prefix\n";
502void Display::ScreenShotCmd::tabCompletion(std::vector<string>& tokens)
const
504 using namespace std::literals;
505 static constexpr std::array extra = {
506 "-prefix"sv,
"-raw"sv,
"-doublesize"sv,
"-with-osd"sv,
"-no-sprites"sv,
"-guess-name"sv,
514Display::FpsInfoTopic::FpsInfoTopic(InfoCommand& openMSXInfoCommand)
515 : InfoTopic(openMSXInfoCommand,
"fps")
519void Display::FpsInfoTopic::execute(std::span<const TclObject> ,
520 TclObject& result)
const
522 auto& display =
OUTER(Display, fpsInfo);
523 result = display.getFps();
526string Display::FpsInfoTopic::help(std::span<const TclObject> )
const
528 return "Returns the current rendering speed in frames per second.";
constexpr T & removeBack()
constexpr void addFront(const T &element)
void printWarning(std::string_view message)
std::string getWindowTitle()
void repaint()
Redraw the display.
gl::ivec2 retrieveWindowPosition()
void detach(VideoSystemChangeListener &listener)
CliComm & getCliComm() const
void storeWindowPosition(gl::ivec2 pos)
void removeLayer(Layer &layer)
VideoSystem & getVideoSystem()
Display(Reactor &reactor)
void attach(VideoSystemChangeListener &listener)
void repaintDelayed(uint64_t delta)
void setWindowPosition(gl::ivec2 pos)
Layer * findActiveLayer() const
OutputSurface * getOutputSurface()
gl::ivec2 getWindowPosition()
Get/set x,y coordinates of top-left window corner.
void addLayer(Layer &layer)
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
void distributeEvent(Event &&event)
Schedule the given event for delivery.
void registerEventListener(EventType type, EventListener &listener, Priority priority=Priority::OTHER)
Registers a given object to receive certain events.
void storeWindowPosition(gl::ivec2 pos)
gl::ivec2 retrieveWindowPosition() const
int getInt() const noexcept
Interface for display layers.
@ NONE
Layer is not visible, that is completely transparent.
@ FULL
Layer fully covers the screen: any underlying layers are invisible.
void setDisplay(LayerListener &display_)
Store pointer to Display.
ZIndex getZ() const
Query the Z-index of this layer.
A frame buffer where pixels can be written to.
void scheduleRT(uint64_t delta)
Contains the main loop of openMSX.
ImGuiManager & getImGuiManager()
MSXMotherBoard * getMotherBoard() const
EventDistributor & getEventDistributor()
RendererSetting & getRendererSetting()
The current renderer.
IntegerSetting & getScaleFactorSetting()
The current scaling factor.
RendererID getRenderer() const
void detach(Observer< T > &observer)
void attach(Observer< T > &observer)
static std::string full()
static const bool RELEASE
string parseCommandFileArgument(string_view argument, string_view directory, string_view prefix, string_view extension)
Helper function for parsing filename arguments in Tcl commands.
std::unique_ptr< VideoSystem > createVideoSystem(Reactor &reactor)
Create the video system required by the current renderer setting.
uint64_t getTime()
Get current (real) time in us.
This file implemented 3 utility functions:
ArgsInfo valueArg(std::string_view name, T &value)
std::vector< TclObject > parseTclArgs(Interpreter &interp, std::span< const TclObject > inArgs, std::span< const ArgsInfo > table)
const FileContext & userFileContext()
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
ArgsInfo flagArg(std::string_view name, bool &flag)
auto find_if(InputRange &&range, UnaryPredicate pred)
#define OUTER(type, member)
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
void strAppend(std::string &result, Ts &&...ts)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)