32#include <imgui_impl_sdl2.h>
33#include <imgui_impl_opengl3.h>
50 , eventDistributor(eventDistributor_)
51 , inputEventGenerator(inputEventGenerator_)
53 , videoSystem(videoSystem_)
58 renderSettings.getPointerHideDelaySetting().attach(*
this);
59 renderSettings.getFullScreenSetting().attach(*
this);
69 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
70 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
71 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
72#if OPENGL_VERSION == OPENGL_ES_2_0
73 #define VERSION_STRING "openGL ES 2.0"
74 const char* glsl_version =
"#version 100";
75 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
76 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
77 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
78#elif OPENGL_VERSION == OPENGL_2_1
79 #define VERSION_STRING "openGL 2.1"
80 const char* glsl_version =
"#version 120";
81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
82 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
83 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
84#elif OPENGL_VERSION == OPENGL_3_3
85 #define VERSION_STRING "openGL 3.3"
86 const char* glsl_version =
"#version 150";
87 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
88 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
89 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
92 int flags = SDL_WINDOW_OPENGL;
95 createSurface(size, flags);
98 glContext = SDL_GL_CreateContext(window.get());
119 glewExperimental = GL_TRUE;
127 if (GLenum glew_error = glewInit();
128 glew_error != GLEW_OK && glew_error != GLEW_ERROR_NO_GLX_DISPLAY) {
130 "Failed to init GLEW: ",
131 std::bit_cast<const char*>(glewGetErrorString(glew_error)));
133 if (!GLEW_VERSION_2_1) {
139 bool fullScreen = renderSettings.getFullScreen();
140 setViewPort(size, fullScreen);
142 renderSettings.getVSyncSetting().attach(vSyncObserver);
144 vSyncObserver.update(renderSettings.getVSyncSetting());
146#if OPENGL_VERSION == OPENGL_3_3
150 glGenVertexArrays(1, &vao);
151 glBindVertexArray(vao);
164 SDL_GL_DeleteContext(glContext);
181 renderSettings.getPointerHideDelaySetting().detach(*
this);
182 renderSettings.getFullScreenSetting().detach(*
this);
187 if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_FULLSCREEN)
return {};
189 SDL_GetWindowPosition(window.get(), &x, &y);
195 if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_FULLSCREEN)
return;
196 SDL_SetWindowPosition(window.get(), pos.x, pos.y);
202void VisibleSurface::createSurface(
gl::ivec2 size,
unsigned flags)
204 if (
getDisplay().getRenderSettings().getFullScreen()) {
205 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
209 flags |= SDL_WINDOW_ALLOW_HIGHDPI;
214 window.reset(SDL_CreateWindow(
220 std::string err = SDL_GetError();
221 throw InitException(
"Could not create window: ", err);
227 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"1");
230 if constexpr (OPENMSX_SET_WINDOW_ICON) {
236 }
catch (MSXException& e) {
238 "Falling back to built in 32x32 icon, because failed to load icon: ",
241 PixelOperations pixelOps;
242 iconSurf.
reset(SDL_CreateRGBSurfaceFrom(
251 pixelOps.getAmask()));
255 SDL_SetColorKey(iconSurf.
get(), SDL_TRUE, 0);
256 SDL_SetWindowIcon(window.get(), iconSurf.
get());
275 guiActive = get_event<ImGuiActiveEvent>(event).getActive();
281void VisibleSurface::updateCursor()
286 (renderSettings.getFullScreen() ||
295 float delay = renderSettings.getPointerHideDelay();
308 auto flags = SDL_GetWindowFlags(window.get());
311 if (
bool currentState = (flags & SDL_WINDOW_FULLSCREEN) != 0;
312 currentState == fullscreen) {
317 if (SDL_SetWindowFullscreen(window.get(),
318 fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) != 0) {
328 SDL_SetWindowSize(window.get(), size.x, size.y);
331 setViewPort(size, fullScreen);
337 SDL_SetWindowTitle(window.get(),
getDisplay().getWindowTitle().c_str());
355 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.
data());
358 [&](
auto i) {
return &buffer[size_t(w) * (h - 1 - i)]; }));
365 SDL_GL_SwapWindow(window.get());
370 return std::make_unique<GLSnow>(
getDisplay());
375 return std::make_unique<OSDGUILayer>(gui);
380 return std::make_unique<ImGuiLayer>(manager);
385 return std::make_unique<OffScreenSurface>(*
this);
388void VisibleSurface::VSyncObserver::update(
const Setting&
setting)
noexcept
391 const auto& syncSetting = visSurface.getDisplay().getRenderSettings().getVSyncSetting();
396 int interval = syncSetting.getBoolean() ? -1 : 0;
398 if ((SDL_GL_SetSwapInterval(interval) < 0) && (interval == -1)) {
402 SDL_GL_SetSwapInterval(1);
406void VisibleSurface::setViewPort(
gl::ivec2 logicalSize,
bool fullScreen)
424 SDL_GL_GetDrawableSize(window.get(), &w, &h);
Wrapper around a SDL_Surface.
void reset(SDL_Surface *surface_=nullptr)
bool getBoolean() const noexcept
void printWarning(std::string_view message)
Represents the output window/screen of openMSX.
gl::ivec2 retrieveWindowPosition()
void storeWindowPosition(gl::ivec2 pos)
RenderSettings & getRenderSettings()
gl::ivec2 getWindowSize() const
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
void registerEventListener(EventType type, EventListener &listener, Priority priority=Priority::OTHER)
Registers a given object to receive certain events.
Thrown when a subsystem initialisation fails.
This class manages the lifetime of a block of memory.
const T * data() const
Returns pointer to the start of the memory buffer.
A frame buffer where pixels can be written to.
gl::ivec2 getLogicalSize() const
gl::ivec2 getViewOffset() const
void calculateViewPort(gl::ivec2 logSize, gl::ivec2 physSize)
gl::ivec2 getViewSize() const
void scheduleRT(uint64_t delta)
BooleanSetting & getVSyncSetting()
VSync [on, off].
bool getFullScreen() const
void detach(Observer< T > &observer)
void attach(Observer< T > &observer)
virtual void showCursor(bool show)=0
An OutputSurface which is visible to the user, such as a window or a full screen display.
void finish()
When a complete frame is finished, call this method.
VisibleSurface(Display &display, RTScheduler &rtScheduler, EventDistributor &eventDistributor, InputEventGenerator &inputEventGenerator, CliComm &cliComm, VideoSystem &videoSystem)
std::unique_ptr< Layer > createImGUILayer(ImGuiManager &manager)
bool signalEvent(const Event &event) override
This method gets called when an event you are subscribed to occurs.
Display & getDisplay() const
static void saveScreenshotGL(const OutputSurface &output, const std::string &filename)
void update(const Setting &setting) noexcept override
void setWindowPosition(gl::ivec2 pos)
void fullScreenUpdated(bool fullScreen)
std::unique_ptr< OutputSurface > createOffScreenSurface()
Create an off-screen OutputSurface which has similar properties as this VisibleSurface.
~VisibleSurface() override
std::unique_ptr< Layer > createSnowLayer()
void executeRT() override
void saveScreenshot(const std::string &filename) override
Save the content of this OutputSurface to a PNG file.
std::optional< gl::ivec2 > getWindowPosition() const
Returns x,y coordinates of top-left window corner, or returns a nullopt when in fullscreen mode.
bool setFullScreen(bool fullscreen)
CliComm & getCliComm() const
std::unique_ptr< Layer > createOSDGUILayer(OSDGUI &gui)
static void setMainWindowId(uint32_t id)
bool ImGui_ImplOpenGL3_Init(const char *glsl_version)
void ImGui_ImplOpenGL3_Shutdown()
bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window *window, void *sdl_gl_context)
void ImGui_ImplSDL2_Shutdown()
std::optional< Context > context
void saveRGBA(size_t width, std::span< const uint32_t * > rowPointers, const std::string &filename)
SDLSurfacePtr load(const std::string &filename, bool want32bpp)
Load the given PNG file in a SDL_Surface.
This file implemented 3 utility functions:
const OpenMSX_Icon openMSX_icon
EventType getType(const Event &event)
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
const FileContext & preferSystemFileContext()
constexpr auto transform(Range &&range, UnaryOp op)
#define OUTER(type, member)
constexpr auto xrange(T e)