Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for additional display modes #1602

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 31 additions & 20 deletions extras/videoDrivers/SDL2/VideoSDL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void VideoSDL2::UpdateCurrentSizes()
SetNewSize(VideoMode(w, h), Extent(w2, h2));
}

bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen)
bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, DisplayMode displayMode)
{
if(!initialized)
return false;
Expand All @@ -113,30 +113,33 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8));
CHECK_SDL(SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1));

int wndPos = SDL_WINDOWPOS_CENTERED;

const int wndPos = SDL_WINDOWPOS_CENTERED;
const auto fullscreen = (displayMode & DisplayMode::Fullscreen) != DisplayMode::None;
const auto resizable = (displayMode & DisplayMode::Resizable) != DisplayMode::None;
const auto requestedSize = fullscreen ? FindClosestVideoMode(size) : size;
const unsigned commonFlags = SDL_WINDOW_OPENGL | (resizable ? SDL_WINDOW_RESIZABLE : 0);
const unsigned fullscreenFlag = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0);

window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
SDL_WINDOW_OPENGL | (fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE));
commonFlags | fullscreenFlag);

// Fallback to non-fullscreen
if(!window && fullscreen)
{
window = SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}
window =
SDL_CreateWindow(title.c_str(), wndPos, wndPos, requestedSize.width, requestedSize.height, commonFlags);

if(!window)
{
PrintError(SDL_GetError());
return false;
}

isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
const auto flags = SDL_GetWindowFlags(window);
SetFullscreenFlag((flags & SDL_WINDOW_FULLSCREEN) != 0);
SetResizableFlag((flags & SDL_WINDOW_RESIZABLE) != 0);
UpdateCurrentSizes();

if(!isFullscreen_)
if(!IsFullscreen())
MoveWindowToCenter();

SDL_Surface* iconSurf =
Expand All @@ -161,27 +164,34 @@ bool VideoSDL2::CreateScreen(const std::string& title, const VideoMode& size, bo
return true;
}

bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
bool VideoSDL2::ResizeScreen(const VideoMode& newSize, DisplayMode displayMode)
{
if(!initialized)
return false;

if(isFullscreen_ != fullscreen)
const auto fullscreen = (displayMode & DisplayMode::Fullscreen) != DisplayMode::None;
const auto resizable = (displayMode & DisplayMode::Resizable) != DisplayMode::None;

if(IsFullscreen() != fullscreen)
{
SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
if(!isFullscreen_)
{
SetFullscreenFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0);
if(!IsFullscreen())
MoveWindowToCenter();
}

if(displayMode_ != displayMode)
{
if(!IsFullscreen())
#if SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetWindowResizable(window, SDL_TRUE);
SDL_SetWindowResizable(window, static_cast<SDL_bool>(resizable));
#endif
MoveWindowToCenter();
}
SetResizableFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_RESIZABLE) != 0);
}

if(newSize != GetWindowSize())
{
if(isFullscreen_)
if(IsFullscreen())
{
auto const targetMode = FindClosestVideoMode(newSize);
SDL_DisplayMode target;
Expand All @@ -203,6 +213,7 @@ bool VideoSDL2::ResizeScreen(const VideoMode& newSize, bool fullscreen)
}
UpdateCurrentSizes();
}

return true;
}

Expand Down Expand Up @@ -265,7 +276,7 @@ bool VideoSDL2::MessageLoop()
{
case SDL_WINDOWEVENT_RESIZED:
{
isFullscreen_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
SetFullscreenFlag((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0);
VideoMode newSize(ev.window.data1, ev.window.data2);
if(newSize != GetWindowSize())
{
Expand Down
4 changes: 2 additions & 2 deletions extras/videoDrivers/SDL2/VideoSDL2.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class VideoSDL2 final : public VideoDriver

bool Initialize() override;

bool CreateScreen(const std::string& title, const VideoMode& size, bool fullscreen) override;
bool ResizeScreen(const VideoMode& newSize, bool fullscreen) override;
bool CreateScreen(const std::string& title, const VideoMode& size, DisplayMode displayMode) override;
bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) override;

void DestroyScreen() override;

Expand Down
29 changes: 15 additions & 14 deletions extras/videoDrivers/WinAPI/WinAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,25 @@ void VideoWinAPI::CleanUp()
/**
* Erstellt das Fenster mit entsprechenden Werten.
*
* @param[in] width Breite des Fensters
* @param[in] height Höhe des Fensters
* @param[in] fullscreen Vollbildmodus ja oder nein
* @param[in] width Breite des Fensters
* @param[in] height Höhe des Fensters
* @param[in] displayMode Fullscreen on/off, window resizable?
*
* @return @p true bei Erfolg, @p false bei Fehler
*
* @bug Hardwarecursor ist bei Fenstermodus sichtbar,
* Cursor deaktivieren ist fehlerhaft
*/
bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen)
bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode)
{
if(!initialized)
return false;

if(!RegisterAndCreateWindow(title, newSize, fullscreen))
if(!RegisterAndCreateWindow(title, newSize, displayMode))
return false;

if(fullscreen && !MakeFullscreen(GetWindowSize()))
if(bitset::isSet(displayMode, DisplayMode::Fullscreen) && !MakeFullscreen(GetWindowSize()))
return false;
isFullscreen_ = fullscreen;

if(!InitOGL())
return false;
Expand All @@ -174,30 +173,31 @@ bool VideoWinAPI::CreateScreen(const std::string& title, const VideoMode& newSiz
*
* @todo Vollbildmodus ggf. wechseln
*/
bool VideoWinAPI::ResizeScreen(const VideoMode& newSize, bool fullscreen)
bool VideoWinAPI::ResizeScreen(const VideoMode& newSize, DisplayMode displayMode)
{
if(!initialized || !isWindowResizable)
return false;

if(isFullscreen_ == fullscreen && newSize == GetWindowSize())
const auto fullscreen = bitset::isSet(displayMode, DisplayMode::Fullscreen);
if(IsFullscreen() == fullscreen && newSize == GetWindowSize())
return true;

ShowWindow(screen, SW_HIDE);

VideoMode windowSize = fullscreen ? FindClosestVideoMode(newSize) : newSize;
// Try to switch full screen first
if(isFullscreen_ && !fullscreen)
if(IsFullscreen() && !fullscreen)
{
if(ChangeDisplaySettings(nullptr, 0) != DISP_CHANGE_SUCCESSFUL)
return false;
} else if(isFullscreen_ || fullscreen)
} else if(IsFullscreen() || fullscreen)
{
if(!MakeFullscreen(windowSize))
return false;
}

// Fensterstyle ggf. ändern
std::pair<DWORD, DWORD> style = GetStyleFlags(isFullscreen_);
std::pair<DWORD, DWORD> style = GetStyleFlags(IsFullscreen());
SetWindowLongPtr(screen, GWL_STYLE, style.first);
SetWindowLongPtr(screen, GWL_EXSTYLE, style.second);

Expand Down Expand Up @@ -253,7 +253,7 @@ RECT VideoWinAPI::CalculateWindowRect(bool fullscreen, VideoMode& size) const
return wRect;
}

bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, bool fullscreen)
bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, DisplayMode displayMode)
{
std::wstring wTitle = boost::nowide::widen(title);
windowClassName = wTitle.substr(0, wTitle.find(' '));
Expand All @@ -275,6 +275,7 @@ bool VideoWinAPI::RegisterAndCreateWindow(const std::string& title, const VideoM
return false;

// Create window
const auto fullscreen = bitset::isSet(displayMode, DisplayMode::Fullscreen);
auto adjWindowSize = fullscreen ? FindClosestVideoMode(wndSize) : wndSize;
RECT wRect = CalculateWindowRect(fullscreen, adjWindowSize);

Expand Down Expand Up @@ -405,7 +406,7 @@ void VideoWinAPI::DestroyScreen()

UnregisterClassW(windowClassName.c_str(), GetModuleHandle(nullptr));

isFullscreen_ = false;
displayMode_ = bitset::set(displayMode_, DisplayMode::Fullscreen, false);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions extras/videoDrivers/WinAPI/WinAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class VideoWinAPI final : public VideoDriver
bool Initialize() override;

/// Erstellt das Fenster mit entsprechenden Werten.
bool CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen) override;
bool CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode) override;

/// Erstellt oder verändert das Fenster mit entsprechenden Werten.
bool ResizeScreen(const VideoMode& newSize, bool fullscreen) override;
bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) override;

/// Schliesst das Fenster.
void DestroyScreen() override;
Expand Down Expand Up @@ -66,7 +66,7 @@ class VideoWinAPI final : public VideoDriver
std::pair<DWORD, DWORD> GetStyleFlags(bool fullscreen) const;
/// Calculate the rect for the window and adjusts the (usable) size if required
RECT CalculateWindowRect(bool fullscreen, VideoMode& size) const;
bool RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, bool fullscreen);
bool RegisterAndCreateWindow(const std::string& title, const VideoMode& wndSize, DisplayMode displayMode);
bool InitOGL();
static bool MakeFullscreen(const VideoMode& resolution);

Expand Down
9 changes: 7 additions & 2 deletions libs/driver/include/driver/VideoDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class VideoDriver : public IVideoDriver

VideoMode GetWindowSize() const override final { return windowSize_; }
Extent GetRenderSize() const override final { return renderSize_; }
bool IsFullscreen() const override final { return isFullscreen_; }
DisplayMode GetDisplayMode() const override final { return displayMode_; }
bool IsFullscreen() const override final { return bitset::isSet(displayMode_, DisplayMode::Fullscreen); }
bool IsResizable() const override final { return bitset::isSet(displayMode_, DisplayMode::Fullscreen); }

/// prüft auf Initialisierung.
bool IsInitialized() const override final { return initialized; }
Expand All @@ -39,11 +41,14 @@ class VideoDriver : public IVideoDriver
VideoMode FindClosestVideoMode(const VideoMode& mode) const;
void SetNewSize(VideoMode windowSize, Extent renderSize);

void SetFullscreenFlag(bool fullscreen) { displayMode_ = fullscreen ? (displayMode_ | DisplayMode::Fullscreen) : (displayMode_ & ~DisplayMode::Fullscreen); }
void SetResizableFlag(bool resizable) { displayMode_ = bitset::set(displayMode_, DisplayMode::Resizable, resizable); }

VideoDriverLoaderInterface* CallBack; /// Das DriverCallback für Rückmeldungen.
bool initialized; /// Initialisierungsstatus.
MouseCoords mouse_xy; /// Status der Maus.
std::array<bool, 512> keyboard; /// Status der Tastatur;
bool isFullscreen_; /// Vollbild an/aus?
DisplayMode displayMode_; /// Fullscreen/resizable?
private:
// cached as possibly used often
VideoMode windowSize_;
Expand Down
90 changes: 88 additions & 2 deletions libs/driver/include/driver/VideoInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,96 @@
#include "Point.h"
#include "VideoMode.h"
#include "exportImport.h"
// #include "s25util/enumUtils.h"
#include <string>
#include <type_traits>
#include <vector>

/// Function type for loading OpenGL methods
using OpenGL_Loader_Proc = void* (*)(const char*);

template<typename Enum>
struct IsBitset : std::false_type
{};

template<typename Enum>
using IsValidBitset =
std::integral_constant<bool, IsBitset<Enum>::value && std::is_unsigned<std::underlying_type_t<Enum>>::value>;

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator~(Enum val) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(~static_cast<T>(val));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator&(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) & static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator|(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) | static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator^(Enum lhs, Enum rhs) noexcept
{
using T = std::underlying_type_t<Enum>;
return Enum(static_cast<T>(lhs) ^ static_cast<T>(rhs));
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator&=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs & rhs;
return lhs;
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator|=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs | rhs;
return lhs;
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr auto operator^=(Enum& lhs, Enum rhs) noexcept
{
lhs = lhs ^ rhs;
return lhs;
}

namespace bitset {
template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
constexpr bool isSet(Enum val, Enum flag)
{
return (val & flag) != Enum(0);
}

template<typename Enum, std::enable_if_t<IsValidBitset<Enum>::value, int> = 0>
[[nodiscard]] constexpr Enum set(Enum val, Enum flag, bool state)
{
return state ? (val | flag) : (val & ~flag);
}
} // namespace bitset

enum class DisplayMode : unsigned
{
None,
Fullscreen = (1 << 0),
Resizable = (1 << 1)
};

template<>
struct IsBitset<DisplayMode> : std::true_type
{};

class BOOST_SYMBOL_VISIBLE IVideoDriver
{
public:
Expand All @@ -25,9 +109,9 @@ class BOOST_SYMBOL_VISIBLE IVideoDriver
virtual bool Initialize() = 0;

/// Erstellt das Fenster mit entsprechenden Werten.
virtual bool CreateScreen(const std::string& title, const VideoMode& newSize, bool fullscreen) = 0;
virtual bool CreateScreen(const std::string& title, const VideoMode& newSize, DisplayMode displayMode) = 0;

virtual bool ResizeScreen(const VideoMode& newSize, bool fullscreen) = 0;
virtual bool ResizeScreen(const VideoMode& newSize, DisplayMode displayMode) = 0;

/// Schliesst das Fenster.
virtual void DestroyScreen() = 0;
Expand Down Expand Up @@ -61,7 +145,9 @@ class BOOST_SYMBOL_VISIBLE IVideoDriver
virtual VideoMode GetWindowSize() const = 0;
/// Get the size of the render region in pixels
virtual Extent GetRenderSize() const = 0;
virtual DisplayMode GetDisplayMode() const = 0;
virtual bool IsFullscreen() const = 0;
virtual bool IsResizable() const = 0;

/// Get state of the modifier keys
virtual KeyEvent GetModKeyState() const = 0;
Expand Down
2 changes: 1 addition & 1 deletion libs/driver/src/VideoDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ IVideoDriver::~IVideoDriver() = default;
* @param[in] CallBack DriverCallback für Rückmeldungen.
*/
VideoDriver::VideoDriver(VideoDriverLoaderInterface* CallBack)
: CallBack(CallBack), initialized(false), isFullscreen_(false), renderSize_(0, 0)
: CallBack(CallBack), initialized(false), displayMode_(DisplayMode::Resizable), renderSize_(0, 0)
{
std::fill(keyboard.begin(), keyboard.end(), false);
}
Expand Down
Loading