Skip to content

Add SDL full screen mode support#33

Merged
benstone merged 15 commits into
benstone:mainfrom
mcayland:feature/sdl-fullscreen
May 26, 2026
Merged

Add SDL full screen mode support#33
benstone merged 15 commits into
benstone:mainfrom
mcayland:feature/sdl-fullscreen

Conversation

@mcayland

Copy link
Copy Markdown
Contributor

This series adds support for full screen mode when using SDL, allowing for a truly immersive experience 3D Movie Maker experience on modern hardware!

The approach taken in this series is to define a new 640 x 480 logical application size, apply the logical size to the renderer, and then allow the renderer to scale the application to fit the window. Along the way there is a minor bugfix for the config INI parser, some changes to the way the renderer and texture are set up, adding logical to window and window to logical conversion functions as needed, and finally the mode switching logic itself.

Since there is no configuration window for SDL builds, the mode switching logical is bound to the Alt-Enter key combination which can be used to switch between 640 x 480 windowed mode and full screen mode whenever the main event loop is running. The SDL mode switch logic also persists the current screen mode so that 3DMMEx will configure itself to use the last selected screen mode upon startup.

Resolves: #17

@benstone benstone left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick test with the Windows SDL build, the scaling works great!

Comment thread kauai/src/gfxsdl.cpp
Comment thread samples/thebook.3mm
mcayland added 15 commits May 26, 2026 22:04
In the case where pfNoValue is set and the provided section key does not
exist, FGetSetRegKey() should return fTrue to indicate the operation
succeeded so that the caller can check pfNoValue for the result.

This is required for the switch resolution logic to work correctly when
looking up the kszSwitchResolutionValue section key when it does not exist.
…urs()

If the logical renderer size is different from the window size as required for
fullscreen mode, SDL_WarpMouseGlobal() does not warp the mouse correctly for
the application window causing jumps when moving actors.

The solution is to use SDL_WarpMouseInWindow() which will correctly take into
account the logical renderer size, but this is slightly complicated in that
APPB::PositionCurs() takes the position in screen coordinates. To avoid
changing the APPB::PositionCurs() API which is also used for non-SDL builds,
convert the screen coordinates back into window coordinates using MapPt() first
before calling SDL_WarpMouseInWindow().
According to the SDL documentation SDL_RenderClear() clears the rendering
target to the current paint colour. Currently this is done every time
GPT::Flip() is called to update the application window causing a noticeable
flicker when the application is running in fullscreen mode.

Clear the rendering target just once at the time the renderer is created
to avoid flickering when updating large sections in the application
window.
This is to reflect that the value represents the logical application size and
not the window size.
This is so that the logical application size can be used outside of appbsdl.cpp.
This ensures that the renderer size is set to the logical application size,
regardless of the size of window.
When the window size is different from the logical size, it is necessary to
convert any window coordinates to logical coordinates. Note that the same
transformation must be applied to SDL_GetMouseState() since compared to a
mouse event, the coordinates returned are always window coordinates.
…size

The rectangle returned by GOB::_SetRcCur() for a GOB with a hwnd is always the
logical application size, and not the window size.
… GPTs

This is because offscreen GPTs are not bound to a window but are instead
backed by a surface.
This will allow for later moving the texture management logic out of
GPT::PgptNew().
This function will be used to reset the renderer and upload a new texture when
changing window size.
Since RebuildTexture() contains all the logic to recreate an SDL texture, use it
in GOB::FAttachHwnd() to avoid having duplicated logic that depends upon the GPT
fOffScreen variable in GPT::PgptNew().
…d renderer

Since the logical application size is fixed there is no need to query the
current renderer to determine the size of the texture. Use kdxpLogical and
kdypLogical directly, which also removes the need to create an initial renderer
in APPB::_FInitOS().
…ed(KAUAI_WIN32)

When attempting to switch window size at startup, APP::_FInitOS() can be called
early. Move the _fMainWindowCreated check outside of the defined(KAUAI_WIN32)
section since it prevents APP::_FInitOS() from being called more than once in all
cases.
Allow switching between windowed and full screen mode by pressing Alt-Enter.
The application now works in a fixed 640x480 resolution but scales the texture
to fit the current window. The current full screen mode state is saved in the
config file so that 3dmovie will retain the screen mode after a restart.

Note that APP::_FDisplayIs640480() and APP::_FSwitch640480() work in the
opposite way that you may expect. This is because the Windows logic assumes
that full sceen *is* 640x480 resolution since if the screen resolution were
larger, 3D Movie Maker would configure the video controller into 640x480 mode
in order to fill the screen.
@mcayland mcayland force-pushed the feature/sdl-fullscreen branch from 1cfc622 to 53d3dca Compare May 26, 2026 21:04
@benstone benstone merged commit 9c8e9bd into benstone:main May 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Full-screen mode

2 participants