32#include <imgui_impl_sdl2.h>
33#include <imgui_impl_opengl3.h>
49 , eventDistributor(eventDistributor_)
50 , inputEventGenerator(inputEventGenerator_)
52 , videoSystem(videoSystem_)
57 renderSettings.getPointerHideDelaySetting().attach(*
this);
58 renderSettings.getFullScreenSetting().attach(*
this);
65 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
66 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
67 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
68#if OPENGL_VERSION == OPENGL_ES_2_0
69 #define VERSION_STRING "openGL ES 2.0"
70 const char* glsl_version =
"#version 100";
71 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
72 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
73 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
74#elif OPENGL_VERSION == OPENGL_2_1
75 #define VERSION_STRING "openGL 2.1"
76 const char* glsl_version =
"#version 120";
77 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
78 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
80#elif OPENGL_VERSION == OPENGL_3_3
81 #define VERSION_STRING "openGL 3.3"
82 const char* glsl_version =
"#version 150";
83 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
84 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
85 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
88 int flags = SDL_WINDOW_OPENGL;
90 auto [width, height] = getWindowSize();
91 createSurface(width, height, flags);
94 glContext = SDL_GL_CreateContext(window.get());
115 glewExperimental = GL_TRUE;
118 GLenum glew_error = glewInit();
125 if (glew_error != GLEW_OK && glew_error != GLEW_ERROR_NO_GLX_DISPLAY) {
127 "Failed to init GLEW: ",
128 reinterpret_cast<const char*
>(
129 glewGetErrorString(glew_error)));
131 if (!GLEW_VERSION_2_1) {
137 bool fullScreen = renderSettings.getFullScreen();
138 setViewPort(
gl::ivec2(width, height), fullScreen);
140 renderSettings.getVSyncSetting().attach(vSyncObserver);
142 vSyncObserver.update(renderSettings.getVSyncSetting());
144#if OPENGL_VERSION == OPENGL_3_3
148 glGenVertexArrays(1, &vao);
149 glBindVertexArray(vao);
162 SDL_GL_DeleteContext(glContext);
176 renderSettings.getPointerHideDelaySetting().detach(*
this);
177 renderSettings.getFullScreenSetting().detach(*
this);
182 if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_FULLSCREEN)
return {};
184 SDL_GetWindowPosition(window.get(), &x, &y);
190 if (SDL_GetWindowFlags(window.get()) & SDL_WINDOW_FULLSCREEN)
return;
191 SDL_SetWindowPosition(window.get(), pos.x, pos.y);
197void VisibleSurface::createSurface(
int width,
int height,
unsigned flags)
199 if (
getDisplay().getRenderSettings().getFullScreen()) {
200 flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
204 flags |= SDL_WINDOW_ALLOW_HIGHDPI;
209 window.reset(SDL_CreateWindow(
215 std::string err = SDL_GetError();
216 throw InitException(
"Could not create window: ", err);
222 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,
"1");
225 if constexpr (OPENMSX_SET_WINDOW_ICON) {
231 }
catch (MSXException& e) {
233 "Falling back to built in 32x32 icon, because failed to load icon: ",
236 PixelOperations pixelOps;
237 iconSurf.
reset(SDL_CreateRGBSurfaceFrom(
246 pixelOps.getAmask()));
250 SDL_SetColorKey(iconSurf.
get(), SDL_TRUE, 0);
251 SDL_SetWindowIcon(window.get(), iconSurf.
get());
270 guiActive = get_event<ImGuiActiveEvent>(event).getActive();
276void VisibleSurface::updateCursor()
281 (renderSettings.getFullScreen() ||
290 float delay = renderSettings.getPointerHideDelay();
303 auto flags = SDL_GetWindowFlags(window.get());
306 bool currentState = (flags & SDL_WINDOW_FULLSCREEN) != 0;
307 if (currentState == fullscreen) {
312 if (SDL_SetWindowFullscreen(window.get(),
313 fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0) != 0) {
320gl::ivec2 VisibleSurface::getWindowSize()
const
324 return {320 * factor, 240 * factor};
329 auto size = getWindowSize();
330 SDL_SetWindowSize(window.get(), size.x, size.y);
333 setViewPort(size, fullScreen);
339 SDL_SetWindowTitle(window.get(),
getDisplay().getWindowTitle().c_str());
355 glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.
data());
357 VLA(
const void*, rowPointers, h);
358 for (
auto i :
xrange(
size_t(h))) {
359 rowPointers[h - 1 - i] = &buffer[4 * size_t(w) * i];
367 SDL_GL_SwapWindow(window.get());
372 return std::make_unique<GLSnow>(
getDisplay());
377 return std::make_unique<OSDGUILayer>(gui);
382 return std::make_unique<ImGuiLayer>(manager);
387 return std::make_unique<OffScreenSurface>(*
this);
390void VisibleSurface::VSyncObserver::update(
const Setting&
setting)
noexcept
393 auto& syncSetting = visSurface.getDisplay().getRenderSettings().getVSyncSetting();
398 int interval = syncSetting.getBoolean() ? -1 : 0;
400 if ((SDL_GL_SetSwapInterval(interval) < 0) && (interval == -1)) {
404 SDL_GL_SetSwapInterval(1);
408void VisibleSurface::setViewPort(
gl::ivec2 logicalSize,
bool fullScreen)
426 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()
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
void registerEventListener(EventType type, EventListener &listener, 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].
int getScaleFactor() const
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)
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
int signalEvent(const Event &event) override
This method gets called when an event you are subscribed to occurs.
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 void * > 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()
#define OUTER(type, member)
#define VLA(TYPE, NAME, LENGTH)
constexpr auto xrange(T e)