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;
82 assert(listeners.empty());
89 assert(!switchInProgress);
91 switchInProgress =
true;
103 return videoSystem ? videoSystem->getOutputSurface() :
nullptr;
106void Display::resetVideoSystem()
121 assert(!
contains(listeners, &listener));
122 listeners.push_back(&listener);
133 return (it != layers.end()) ? *it :
nullptr;
136Display::Layers::iterator Display::baseLayer()
140 auto it =
end(layers);
142 if (it ==
begin(layers)) {
155void Display::executeRT()
160int Display::signalEvent(
const Event& event)
163 [&](
const FinishFrameEvent&
e) {
164 if (
e.needRender()) {
169 [&](
const SwitchRendererEvent& ) {
172 [&](
const MachineLoadedEvent& ) {
173 videoSystem->updateWindowTitle();
175 [&](
const WindowEvent&
e) {
176 const auto& evt =
e.getSdlWindowEvent();
177 if (evt.event == SDL_WINDOWEVENT_EXPOSED) {
183 evt.event ==
one_of(SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_FOCUS_LOST)) {
199 bool lost = evt.event == SDL_WINDOWEVENT_FOCUS_LOST;
200 ad_printf(
"Setting renderFrozen to %d", lost);
204 [](
const EventBase&) { }
213 strAppend(title,
" [", BUILD_FLAVOUR,
']');
216 if (
const HardwareConfig* machine = motherboard->getMachineConfig()) {
217 const auto& config = machine->getConfig();
219 config.getChild(
"info").getChildData(
"manufacturer"),
' ',
220 config.getChild(
"info").getChildData(
"code"));
228 if (
auto pos = videoSystem->getWindowPosition()) {
237 videoSystem->setWindowPosition(pos);
252 if (&
setting == &renderSettings.getRendererSetting()) {
253 checkRendererSwitch();
259void Display::checkRendererSwitch()
261 if (switchInProgress) {
268 if (newRenderer != currentRenderer) {
269 currentRenderer = newRenderer;
273 switchInProgress =
true;
278void Display::doRendererSwitch()
280 assert(switchInProgress);
282 bool success =
false;
287 }
catch (MSXException& e) {
290 "Couldn't activate renderer ",
291 rendererSetting.getString(),
292 ": ",
e.getMessage());
295 auto curVal = scaleFactorSetting.
getInt();
299 " (and I have no other ideas to try...)");
301 strAppend(errorMsg,
"\nTrying to decrease scale_factor setting from ",
302 curVal,
" to ", curVal - 1,
"...");
303 scaleFactorSetting.setInt(curVal - 1);
308 switchInProgress =
false;
311void Display::doRendererSwitch2()
313 for (
auto& l : listeners) {
314 l->preVideoSystemChange();
320 for (
auto& l : listeners) {
321 l->postVideoSystemChange();
327 if (switchInProgress) {
342 if (
OutputSurface* surface = videoSystem->getOutputSurface()) {
344 videoSystem->flush();
350 auto duration = now - prevTimeStamp;
352 frameDurationSum += duration - frameDurations.
removeBack();
362 for (
auto it = baseLayer(); it !=
end(layers); ++it) {
364 (*it)->paint(surface);
373 videoSystem->repaint();
387 int z = layer.
getZ();
389 layers.insert(it, &layer);
398void Display::updateZ(
Layer& layer)
noexcept
409Display::ScreenShotCmd::ScreenShotCmd(CommandController& commandController_)
410 : Command(commandController_,
"screenshot")
414void Display::ScreenShotCmd::execute(std::span<const TclObject> tokens, TclObject& result)
416 std::string_view prefix =
"openmsx";
417 bool rawShot =
false;
418 bool msxOnly =
false;
419 bool doubleSize =
false;
420 bool withOsd =
false;
425 flagArg(
"-doublesize", doubleSize),
428 auto arguments =
parseTclArgs(getInterpreter(), tokens.subspan(1), info);
430 auto& display =
OUTER(Display, screenShotCmd);
432 display.getCliComm().printWarning(
433 "The -msxonly option has been deprecated and will "
434 "be removed in a future release. Instead, use the "
435 "-raw option for the same effect.");
438 if (doubleSize && !rawShot) {
439 throw CommandException(
"-doublesize option can only be used in "
440 "combination with -raw");
442 if (rawShot && withOsd) {
443 throw CommandException(
"-with-osd cannot be used in "
444 "combination with -raw");
447 std::string_view fname;
448 switch (arguments.size()) {
453 fname = arguments[0].getString();
459 fname, SCREENSHOT_DIR, prefix, SCREENSHOT_EXTENSION);
464 display.getVideoSystem().takeScreenShot(filename, withOsd);
465 }
catch (MSXException& e) {
466 throw CommandException(
467 "Failed to take screenshot: ",
e.getMessage());
470 auto* videoLayer =
dynamic_cast<VideoLayer*
>(
471 display.findActiveLayer());
473 throw CommandException(
474 "Current renderer doesn't support taking screenshots.");
476 unsigned height = doubleSize ? 480 : 240;
478 videoLayer->takeRawScreenShot(height, filename);
479 }
catch (MSXException& e) {
480 throw CommandException(
481 "Failed to take screenshot: ",
e.getMessage());
485 display.getCliComm().printInfo(
"Screen saved to ", filename);
489string Display::ScreenShotCmd::help(std::span<const TclObject> )
const
494 return "screenshot Write screenshot to file \"openmsxNNNN.png\"\n"
495 "screenshot <filename> Write screenshot to indicated file\n"
496 "screenshot -prefix foo Write screenshot to file \"fooNNNN.png\"\n"
497 "screenshot -raw 320x240 raw screenshot (of MSX screen only)\n"
498 "screenshot -raw -doublesize 640x480 raw screenshot (of MSX screen only)\n"
499 "screenshot -with-osd Include OSD elements in the screenshot\n"
500 "screenshot -no-sprites Don't include sprites in the screenshot\n"
501 "screenshot -guess-name Guess the name of the running software and use it as prefix\n";
504void Display::ScreenShotCmd::tabCompletion(std::vector<string>& tokens)
const
506 using namespace std::literals;
507 static constexpr std::array extra = {
508 "-prefix"sv,
"-raw"sv,
"-doublesize"sv,
"-with-osd"sv,
"-no-sprites"sv,
"-guess-name"sv,
516Display::FpsInfoTopic::FpsInfoTopic(InfoCommand& openMSXInfoCommand)
517 : InfoTopic(openMSXInfoCommand,
"fps")
521void Display::FpsInfoTopic::execute(std::span<const TclObject> ,
522 TclObject& result)
const
524 auto& display =
OUTER(Display, fpsInfo);
525 result = 1000000.0f * Display::NUM_FRAME_DURATIONS / narrow_cast<float>(display.frameDurationSum);
528string Display::FpsInfoTopic::help(std::span<const TclObject> )
const
530 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=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.
@ COVER_FULL
Layer fully covers the screen: any underlying layers are invisible.
@ COVER_NONE
Layer is not visible, that is completely transparent.
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)