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);
249 return {320 * factor, 240 * factor};
254 return 1000000.0f * NUM_FRAME_DURATIONS / narrow_cast<float>(frameDurationSum);
259 assert(&
setting == &renderSettings.getRendererSetting()); (void)
setting;
260 checkRendererSwitch();
263void Display::checkRendererSwitch()
265 if (switchInProgress) {
272 if (newRenderer != currentRenderer) {
273 currentRenderer = newRenderer;
277 switchInProgress =
true;
282void Display::doRendererSwitch()
284 assert(switchInProgress);
286 bool success =
false;
291 }
catch (MSXException& e) {
294 "Couldn't activate renderer ",
295 rendererSetting.getString(),
296 ": ",
e.getMessage());
299 auto curVal = scaleFactorSetting.
getInt();
303 " (and I have no other ideas to try...)");
305 strAppend(errorMsg,
"\nTrying to decrease scale_factor setting from ",
306 curVal,
" to ", curVal - 1,
"...");
307 scaleFactorSetting.setInt(curVal - 1);
312 switchInProgress =
false;
315void Display::doRendererSwitch2()
317 for (
auto& l : listeners) {
318 l->preVideoSystemChange();
324 for (
auto& l : listeners) {
325 l->postVideoSystemChange();
331 if (switchInProgress) {
346 if (
OutputSurface* surface = videoSystem->getOutputSurface()) {
348 videoSystem->flush();
354 auto duration = now - prevTimeStamp;
356 frameDurationSum += duration - frameDurations.
pop_back();
366 for (
auto it = baseLayer(); it !=
end(layers); ++it) {
368 (*it)->paint(surface);
377 videoSystem->repaint();
391 auto z = layer.
getZ();
393 layers.insert(it, &layer);
405 auto z = layer.
getZ();
408 if (oldPos == newPos) {
410 }
else if (oldPos < newPos) {
411 std::rotate(oldPos, oldPos + 1, newPos);
413 std::rotate(newPos, oldPos, oldPos + 1);
421 :
Command(commandController_,
"screenshot")
425void Display::ScreenShotCmd::execute(std::span<const TclObject> tokens, TclObject& result)
427 std::string_view prefix =
"openmsx";
428 bool rawShot =
false;
429 bool msxOnly =
false;
430 bool doubleSize =
false;
431 bool withOsd =
false;
436 flagArg(
"-doublesize", doubleSize),
439 auto arguments =
parseTclArgs(getInterpreter(), tokens.subspan(1), info);
441 auto& display =
OUTER(Display, screenShotCmd);
443 display.getCliComm().printWarning(
444 "The -msxonly option has been deprecated and will "
445 "be removed in a future release. Instead, use the "
446 "-raw option for the same effect.");
449 if (doubleSize && !rawShot) {
450 throw CommandException(
"-doublesize option can only be used in "
451 "combination with -raw");
453 if (rawShot && withOsd) {
454 throw CommandException(
"-with-osd cannot be used in "
455 "combination with -raw");
458 std::string_view fname;
459 switch (arguments.size()) {
464 fname = arguments[0].getString();
470 fname, SCREENSHOT_DIR, prefix, SCREENSHOT_EXTENSION);
475 display.getVideoSystem().takeScreenShot(filename, withOsd);
476 }
catch (MSXException& e) {
477 throw CommandException(
478 "Failed to take screenshot: ",
e.getMessage());
481 auto* videoLayer =
dynamic_cast<VideoLayer*
>(
482 display.findActiveLayer());
484 throw CommandException(
485 "Current renderer doesn't support taking screenshots.");
487 unsigned height = doubleSize ? 480 : 240;
489 videoLayer->takeRawScreenShot(height, filename);
490 }
catch (MSXException& e) {
491 throw CommandException(
492 "Failed to take screenshot: ",
e.getMessage());
496 display.getCliComm().printInfo(
"Screen saved to ", filename);
500string Display::ScreenShotCmd::help(std::span<const TclObject> )
const
505 return "screenshot Write screenshot to file \"openmsxNNNN.png\"\n"
506 "screenshot <filename> Write screenshot to indicated file\n"
507 "screenshot -prefix foo Write screenshot to file \"fooNNNN.png\"\n"
508 "screenshot -raw 320x240 raw screenshot (of MSX screen only)\n"
509 "screenshot -raw -doublesize 640x480 raw screenshot (of MSX screen only)\n"
510 "screenshot -with-osd Include OSD elements in the screenshot\n"
511 "screenshot -no-sprites Don't include sprites in the screenshot\n"
512 "screenshot -guess-name Guess the name of the running software and use it as prefix\n";
515void Display::ScreenShotCmd::tabCompletion(std::vector<string>& tokens)
const
517 using namespace std::literals;
518 static constexpr std::array extra = {
519 "-prefix"sv,
"-raw"sv,
"-doublesize"sv,
"-with-osd"sv,
"-no-sprites"sv,
"-guess-name"sv,
527Display::FpsInfoTopic::FpsInfoTopic(InfoCommand& openMSXInfoCommand)
528 : InfoTopic(openMSXInfoCommand,
"fps")
532void Display::FpsInfoTopic::execute(std::span<const TclObject> ,
533 TclObject& result)
const
535 auto& display =
OUTER(Display, fpsInfo);
536 result = display.getFps();
539string Display::FpsInfoTopic::help(std::span<const TclObject> )
const
541 return "Returns the current rendering speed in frames per second.";
constexpr void push_front(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 updateZ(Layer &layer)
void removeLayer(Layer &layer)
VideoSystem & getVideoSystem()
Display(Reactor &reactor)
void attach(VideoSystemChangeListener &listener)
gl::ivec2 getWindowSize() const
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(Display &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
int getScaleFactor() 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)