OXYGENHUB
◆ main openmsx / src / video / SDLVideoSystem.cc
5.6 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "SDLVideoSystem.hh"
2
3
#include "Display.hh"
4
#include "GlobalSettings.hh"
5
#include "PostProcessor.hh"
6
#include "RenderSettings.hh"
7
#include "SDLRasterizer.hh"
8
#include "V9990.hh"
9
#include "V9990SDLRasterizer.hh"
10
#include "VDP.hh"
11
#include "VisibleSurface.hh"
12
13
#include "EventDistributor.hh"
14
#include "IntegerSetting.hh"
15
#include "Reactor.hh"
16
17
#include "unreachable.hh"
18
19
#include "imgui.h"
20
21
#include <memory>
22
23
#include "components.hh"
24
#if COMPONENT_LASERDISC
25
#include "LDSDLRasterizer.hh"
26
#include "LaserdiscPlayer.hh"
27
#endif
28
29
namespace openmsx {
30
31
SDLVideoSystem::SDLVideoSystem(Reactor& reactor_)
32
	: reactor(reactor_)
33
	, display(reactor.getDisplay())
34
	, renderSettings(reactor.getDisplay().getRenderSettings())
35
{
36
	screen = std::make_unique<VisibleSurface>(
37
		display,
38
		reactor.getRTScheduler(), reactor.getEventDistributor(),
39
		reactor.getInputEventGenerator(), reactor.getCliComm(),
40
		*this, reactor.getGlobalSettings().getPauseSetting());
41
42
	snowLayer = screen->createSnowLayer();
43
	osdGuiLayer = screen->createOSDGUILayer(display.getOSDGUI());
44
	imGuiLayer = screen->createImGUILayer(reactor.getImGuiManager());
45
	display.addLayer(*snowLayer);
46
	display.addLayer(*osdGuiLayer);
47
	display.addLayer(*imGuiLayer);
48
49
	renderSettings.getFullScreenSetting().attach(*this);
50
	renderSettings.getScaleFactorSetting().attach(*this);
51
}
52
53
SDLVideoSystem::~SDLVideoSystem()
54
{
55
	renderSettings.getScaleFactorSetting().detach(*this);
56
	renderSettings.getFullScreenSetting().detach(*this);
57
58
	display.removeLayer(*imGuiLayer);
59
	display.removeLayer(*osdGuiLayer);
60
	display.removeLayer(*snowLayer);
61
}
62
63
std::unique_ptr<Rasterizer> SDLVideoSystem::createRasterizer(VDP& vdp)
64
{
65
	assert(display.getRenderer() == RenderSettings::RendererID::SDLGL_PP);
66
	std::string videoSource = (vdp.getName() == "VDP")
67
	                        ? "MSX" // for backwards compatibility
68
	                        : vdp.getName();
69
	auto& motherBoard = vdp.getMotherBoard();
70
	return std::make_unique<SDLRasterizer>(
71
		vdp, display, *screen,
72
		std::make_unique<PostProcessor>(
73
			motherBoard, display, *screen,
74
			videoSource, 640, 240, true));
75
}
76
77
std::unique_ptr<V9990Rasterizer> SDLVideoSystem::createV9990Rasterizer(
78
	V9990& vdp)
79
{
80
	assert(display.getRenderer() == RenderSettings::RendererID::SDLGL_PP);
81
	std::string videoSource = (vdp.getName() == "Sunrise GFX9000")
82
	                        ? "GFX9000" // for backwards compatibility
83
	                        : vdp.getName();
84
	MSXMotherBoard& motherBoard = vdp.getMotherBoard();
85
	return std::make_unique<V9990SDLRasterizer>(
86
		vdp, display, *screen,
87
		std::make_unique<PostProcessor>(
88
			motherBoard, display, *screen,
89
			videoSource, 1280, 240, true));
90
}
91
92
#if COMPONENT_LASERDISC
93
std::unique_ptr<LDRasterizer> SDLVideoSystem::createLDRasterizer(
94
	LaserdiscPlayer& ld)
95
{
96
	assert(display.getRenderer() == RenderSettings::RendererID::SDLGL_PP);
97
	std::string videoSource = "Laserdisc"; // TODO handle multiple???
98
	MSXMotherBoard& motherBoard = ld.getMotherBoard();
99
	return std::make_unique<LDSDLRasterizer>(
100
		std::make_unique<PostProcessor>(
101
			motherBoard, display, *screen,
102
			videoSource, 640, 480, false));
103
}
104
#endif
105
106
void SDLVideoSystem::flush()
107
{
108
	screen->finish();
109
}
110
111
void SDLVideoSystem::takeScreenShot(const std::string& filename, bool withOsd)
112
{
113
	if (withOsd) {
114
		// we can directly save current content as screenshot
115
		screen->saveScreenshot(filename);
116
	} else {
117
		// we first need to re-render to an off-screen surface
118
		// with OSD layers disabled
119
		ScopedLayerHider hideOsd(*osdGuiLayer);
120
		ScopedLayerHider hideImgui(*imGuiLayer);
121
		std::unique_ptr<OutputSurface> surf = screen->createOffScreenSurface();
122
		display.repaintImpl(*surf);
123
		surf->saveScreenshot(filename);
124
	}
125
}
126
127
void SDLVideoSystem::updateWindowTitle()
128
{
129
	screen->updateWindowTitle();
130
}
131
132
std::optional<gl::ivec2> SDLVideoSystem::getMouseCoord()
133
{
134
	return screen->getMouseCoord();
135
}
136
137
std::optional<gl::vec2> SDLVideoSystem::getMsxPixelSize()
138
{
139
	return screen->getMsxPixelSize();
140
}
141
142
OutputSurface* SDLVideoSystem::getOutputSurface()
143
{
144
	return screen.get();
145
}
146
147
void SDLVideoSystem::showCursor(bool show)
148
{
149
	SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
150
	if (show) {
151
		ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
152
	} else {
153
		ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
154
	}
155
}
156
157
bool SDLVideoSystem::getCursorEnabled()
158
{
159
	return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE;
160
}
161
162
std::string SDLVideoSystem::getClipboardText()
163
{
164
	std::string result;
165
	if (char* text = SDL_GetClipboardText()) {
166
		result = text;
167
		SDL_free(text);
168
	}
169
	return result;
170
}
171
172
void SDLVideoSystem::setClipboardText(zstring_view text)
173
{
174
	if (SDL_SetClipboardText(text.c_str()) != 0) {
175
		const char* err = SDL_GetError();
176
		SDL_ClearError();
177
		throw CommandException(err);
178
	}
179
}
180
181
std::optional<gl::ivec2> SDLVideoSystem::getWindowPosition()
182
{
183
	return screen->getWindowPosition();
184
}
185
186
void SDLVideoSystem::setWindowPosition(gl::ivec2 pos)
187
{
188
	screen->setWindowPosition(pos);
189
}
190
191
void SDLVideoSystem::repaint()
192
{
193
	// With SDL we can simply repaint the display directly.
194
	display.repaintImpl();
195
}
196
197
void SDLVideoSystem::update(const Setting& subject) noexcept
198
{
199
	if (&subject == &renderSettings.getFullScreenSetting()) {
200
		screen->setFullScreen(renderSettings.getFullScreen());
201
	} else if (&subject == &renderSettings.getScaleFactorSetting()) {
202
		screen->resize();
203
	} else {
204
		UNREACHABLE;
205
	}
206
}
207
208
bool SDLVideoSystem::signalEvent(const Event& /*event*/)
209
{
210
	// TODO: Currently window size depends only on scale factor.
211
	//       Maybe in the future it will be handled differently.
212
	//const auto& resizeEvent = get_event<ResizeEvent>(event);
213
	//resize(resizeEvent.getX(), resizeEvent.getY());
214
	//resize();
215
	return false;
216
}
217
218
} // namespace openmsx