diff --git a/examples/14_display.cpp b/examples/14_display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6eacab514d092c1cd37a8781d3666fadf30d049 --- /dev/null +++ b/examples/14_display.cpp @@ -0,0 +1,47 @@ +#include <cstdio> +#include <cerrno> + +#include <iostream> + +#include "simple/graphical/initializer.h" + +using namespace simple::graphical; + +std::ostream& operator<<(std::ostream& os, display::mode mode) +{ + os << to_string(mode.format) << ' ' + << mode.size.x() << 'x' << mode.size.y() << '@' + << mode.refresh_rate; + return os; +} + +int main() try +{ + initializer graphics; + + for(auto&& display : graphics.displays()) + { + std::cout << "---Didplay---"<< '\n'; + for(auto&& mode : display.modes()) + { + std::cout << mode; + if(mode == display.current_mode()) + std::cout << " <--"; + std::cout << '\n'; + } + std::cout << '\n'; + } + + return 0; +} +catch(...) +{ + if(errno) + std::perror("ERROR"); + + const char* sdl_error = SDL_GetError(); + if(*sdl_error) + std::puts(sdl_error); + + throw; +} diff --git a/source/simple/graphical.hpp b/source/simple/graphical.hpp index c6d2aa241fdafe6a261e05f3c96d919704271e60..e98fd59edc722dbfe34889298f081e37a478f977 100644 --- a/source/simple/graphical.hpp +++ b/source/simple/graphical.hpp @@ -2,6 +2,7 @@ #include "graphical/color.h" #include "graphical/color_vector.hpp" #include "graphical/common_def.h" +#include "graphical/display.h" #include "graphical/gl_window.h" #include "graphical/initializer.h" #include "graphical/palette_view.h" diff --git a/source/simple/graphical/display.cpp b/source/simple/graphical/display.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02a8f9b6c8349d0efd86fa7e44ccd4e55002838b --- /dev/null +++ b/source/simple/graphical/display.cpp @@ -0,0 +1,145 @@ +#include "display.h" + +namespace simple::graphical +{ + + namespace detail + { + + template <typename Derived, typename... Payload> + Derived& index_iterator<Derived,Payload...>::operator++() noexcept + { + ++index; + return static_cast<Derived&>(*this); + } + + template <typename Derived, typename... Payload> + Derived index_iterator<Derived,Payload...>::operator++(int) noexcept + { + Derived temp = static_cast<Derived&>(*this); + ++(*this); + return temp; + } + + template <typename Derived, typename... Payload> + bool index_iterator<Derived,Payload...>::operator==(const Derived& other) const noexcept + { + return index == other.index; + } + + template <typename Derived, typename... Payload> + bool index_iterator<Derived,Payload...>::operator!=(const Derived& other) const noexcept + { + return !(*this == other); + } + + template <typename Derived, typename... Payload> + int index_iterator<Derived,Payload...>::operator-(const Derived& other) const noexcept + { + return index - other.index; + } + + template <typename Derived, typename... Payload> + index_iterator<Derived,Payload...>::index_iterator(protector, int index, Payload... payload) noexcept + : index(index), payload{payload...} + { } + + template <typename Iterator, typename... Payload> + Iterator index_list<Iterator,Payload...>::make_iterator(int index) const noexcept + { + using protector = typename Iterator::protector; + return std::make_from_tuple<Iterator>( + std::tuple_cat( + std::tuple{protector{},index}, + payload + ) + ); + } + + template <typename Iterator, typename... Payload> + Iterator index_list<Iterator,Payload...>::begin() const noexcept + { + return make_iterator(0); + } + + template <typename Iterator, typename... Payload> + Iterator index_list<Iterator,Payload...>::end() const noexcept + { + return make_iterator(count); + } + + template <typename Iterator,typename... Payload> + index_list<Iterator,Payload...>::index_list(int count, Payload... payload) noexcept + : count(count), payload{payload...} + { } + + template class index_iterator<display::mode_iterator,int>; + template class index_list<display::mode_iterator, int>; + template class index_iterator<display_iterator>; + template class index_list<display_iterator>; + + } // namespace detail + + display::mode from_sdl_mode(const SDL_DisplayMode& mode) + { + return { + static_cast<pixel_format::type>(mode.format), + {mode.w, mode.h}, + mode.refresh_rate + }; + } + + bool display::mode::operator==(const mode& other) const noexcept + { + return other.format == format && + other.size == size && + other.refresh_rate == refresh_rate; + } + + bool display::mode::operator!=(const mode& other) const noexcept + { + return !operator==(other); + } + + auto display::mode_iterator::operator*() const -> mode + { + SDL_DisplayMode mode; + int display_index = std::get<0>(payload); + sdlcore::utils::throw_error( + SDL_GetDisplayMode(display_index, index, &mode)); + return from_sdl_mode(mode); + } + + auto display::current_mode() const -> mode + { + SDL_DisplayMode mode; + sdlcore::utils::throw_error( + SDL_GetCurrentDisplayMode(index, &mode)); + return from_sdl_mode(mode); + } + + auto display::initial_mode() const -> mode + { + SDL_DisplayMode mode; + sdlcore::utils::throw_error( + SDL_GetDesktopDisplayMode(index, &mode)); + return from_sdl_mode(mode); + } + + auto display::modes() const noexcept -> mode_list + { + auto count = SDL_GetNumDisplayModes(index); + if(count < 0) + count = 0; + return mode_list(count, index); + } + + display::display(int index) noexcept : index(index) + { } + + display display_iterator::operator*() const + { + return display(index); + } + +} // namespace simple::graphical diff --git a/source/simple/graphical/display.h b/source/simple/graphical/display.h new file mode 100644 index 0000000000000000000000000000000000000000..d711494dde96988a87080b15eb9f74d182e89f57 --- /dev/null +++ b/source/simple/graphical/display.h @@ -0,0 +1,113 @@ +#ifndef SIMPLE_GRAPHICAL_DISPLAY_H +#define SIMPLE_GRAPHICAL_DISPLAY_H + +#include "common_def.h" +#include "pixel_format.h" + +namespace simple::graphical +{ + + namespace detail + { + + // there is probably some library that does this better... + // maybe boost/iterator?? + template <typename Derived, typename... Payload> + class index_iterator + { + protected: + + class protector {}; + + public: + Derived& operator++() noexcept; + Derived operator++(int) noexcept; + bool operator==(const Derived&) const noexcept; + bool operator!=(const Derived&) const noexcept; + int operator-(const Derived&) const noexcept; + + explicit index_iterator(protector, int, Payload...) noexcept; + + protected: + int index; + std::tuple<Payload...> payload; + }; + + template <typename Iterator, typename... Payload> + class index_list + { + public: + Iterator begin() const noexcept; + Iterator end() const noexcept; + + protected: + explicit index_list(int, Payload...) noexcept; + private: + Iterator make_iterator(int) const noexcept; + int count; + std::tuple<Payload...> payload; + }; + + } // namespace detail + + class display + { + public: + + struct mode + { + pixel_format::type format; + int2 size; + int refresh_rate; + bool operator==(const mode&) const noexcept; + bool operator!=(const mode&) const noexcept; + }; + + class mode_iterator : public detail::index_iterator<mode_iterator,int> + { + public: + using index_iterator<mode_iterator,int>::index_iterator; + mode operator*() const; + + friend class detail::index_list<mode_iterator, int>; + }; + + class mode_list : public detail::index_list<mode_iterator, int> + { + private: + using index_list<mode_iterator,int>::index_list; + friend display; + }; + + mode current_mode() const; + mode initial_mode() const; + mode_list modes() const noexcept; + // TODO: bounds, DPI + private: + explicit display(int) noexcept; + int index; + + friend class display_iterator; + friend class window; + }; + + class display_iterator : public detail::index_iterator<display_iterator> + { + public: + using index_iterator<display_iterator>::index_iterator; + display operator*() const; + + friend class detail::index_list<display_iterator>; + }; + + class display_list : public detail::index_list<display_iterator> + { + private: + using index_list<display_iterator>::index_list; + friend class initializer; + }; + + +} // namespace simple::graphical + +#endif /* end of include guard */ diff --git a/source/simple/graphical/initializer.cpp b/source/simple/graphical/initializer.cpp index e76fd76422cf61767fc019c83677bf04119d6692..eb3ce595cb6573cda842646ed7526232d7766fe2 100644 --- a/source/simple/graphical/initializer.cpp +++ b/source/simple/graphical/initializer.cpp @@ -66,3 +66,11 @@ initializer::screensaver_control::~screensaver_control() noexcept initializer::initializer() : sdlcore::initializer(sdlcore::system_flag::video), screensaver() {} + +display_list initializer::displays() const noexcept +{ + auto count = SDL_GetNumVideoDisplays(); + if(count < 0) + count = 0; + return display_list(count); +} diff --git a/source/simple/graphical/initializer.h b/source/simple/graphical/initializer.h index 1f85198e18262247d4e9c84c41932b35aab5180a..f30cb14bb2393a16438c22bc621dfe30de4aa671 100644 --- a/source/simple/graphical/initializer.h +++ b/source/simple/graphical/initializer.h @@ -2,6 +2,8 @@ #define SIMPLE_GRAPHICAL_INITIALIZER_H #include "simple/sdlcore/initializer.h" +#include "display.h" + namespace simple::graphical { @@ -27,6 +29,7 @@ namespace simple::graphical public: initializer(); screensaver_control screensaver; + display_list displays() const noexcept; }; } // namespace simple::graphical diff --git a/source/simple/graphical/pixel_format.cpp b/source/simple/graphical/pixel_format.cpp index 0d418a8e0aef338b9d776888757f5e86599856d6..9602db66918b671a69384b79c38a21bcc031814f 100644 --- a/source/simple/graphical/pixel_format.cpp +++ b/source/simple/graphical/pixel_format.cpp @@ -1,4 +1,5 @@ #include <type_traits> +#include "simple/support/enum.hpp" #include "pixel_format.h" #include "palette_view.h" @@ -63,4 +64,9 @@ namespace simple::graphical return SDL_GetPixelFormatName(guts()->format); } + const char* to_string(pixel_format::type type) noexcept + { + return SDL_GetPixelFormatName(support::to_integer(type)); + } + } // namespace simple::graphical diff --git a/source/simple/graphical/pixel_format.h b/source/simple/graphical/pixel_format.h index 217cd7441ebd67a0ccd07f6c30c718c29a210301..dea460ddf8438f39795677a15c3a1ee36edfd837 100644 --- a/source/simple/graphical/pixel_format.h +++ b/source/simple/graphical/pixel_format.h @@ -1,9 +1,7 @@ #ifndef SIMPLE_GRAPHICAL_PIXEL_FORMAT_H #define SIMPLE_GRAPHICAL_PIXEL_FORMAT_H -#include <memory> #include <optional> -#include <SDL2/SDL.h> #include "simple/sdlcore/utils.hpp" #include "color.h" #include "palette_view.h" @@ -96,6 +94,8 @@ namespace simple::graphical friend surface convert(const surface& source, const pixel_format& format); }; + const char* to_string(pixel_format::type) noexcept; + } // namespace simple::graphical #endif /* end of include guard */ diff --git a/source/simple/graphical/window.cpp b/source/simple/graphical/window.cpp index dcb58b829f50041c24a2ac6b0066ac75e1875f7d..3a0ac46f93b73cf848ea3639cde5b24a871a245d 100644 --- a/source/simple/graphical/window.cpp +++ b/source/simple/graphical/window.cpp @@ -108,4 +108,11 @@ namespace simple::graphical return SDL_GetWindowID(guts().get()); } + display window::display() const + { + int index = SDL_GetWindowDisplayIndex(guts().get()); + sdlcore::utils::throw_error(index < 0); + return graphical::display(index); + } + } // namespace simple::graphical diff --git a/source/simple/graphical/window.h b/source/simple/graphical/window.h index a5b90ed01685f4c305661671c7deb730c82c38d0..f74c78dc3f402733e6f9df3eae6aeb32f906e7f1 100644 --- a/source/simple/graphical/window.h +++ b/source/simple/graphical/window.h @@ -9,6 +9,7 @@ #include "simple/sdlcore/utils.hpp" #include "common_def.h" +#include "display.h" namespace simple::graphical { @@ -80,6 +81,8 @@ namespace simple::graphical uint32_t id() const noexcept; + graphical::display display() const; + protected: window