35 #include <SDL2/SDL_render.h> 41 #define LOG_DP LOG_STREAM(info, log_display) 42 #define ERR_DP LOG_STREAM(err, log_display) 48 surface drawingSurface =
nullptr;
49 bool fake_interactive =
false;
51 const unsigned MAGIC_DPI_SCALE_NUMBER = 96;
59 : sdl_handler(auto_join)
61 draw_layers.push_back(
this);
66 draw_layers.remove(
this);
74 event.type = SDL_WINDOWEVENT;
75 event.window.event = SDL_WINDOWEVENT_RESIZED;
76 event.window.data1 = (*drawingSurface).h;
77 event.window.data2 = (*drawingSurface).w;
79 for(
const auto& layer : draw_layers) {
80 layer->handle_window_event(event);
87 drawEvent.user = data;
89 SDL_PushEvent(&drawEvent);
96 , drawing_texture_(nullptr)
122 const int res = SDL_InitSubSystem(SDL_INIT_VIDEO);
125 ERR_DP <<
"Could not initialize SDL_video: " << SDL_GetError() << std::endl;
132 LOG_DP <<
"calling SDL_Quit()\n";
136 LOG_DP <<
"called SDL_Quit()\n";
141 return fake_interactive ? false : (
window ==
nullptr);
146 if(event.type == SDL_WINDOWEVENT) {
147 switch(event.window.event) {
148 case SDL_WINDOWEVENT_RESIZED:
149 case SDL_WINDOWEVENT_RESTORED:
150 case SDL_WINDOWEVENT_SHOWN:
151 case SDL_WINDOWEVENT_EXPOSED:
158 drawEvent.user = data;
161 SDL_PushEvent(&drawEvent);
170 SDL_Rect dst{x, y, 0, 0};
172 const clip_rect_setter clip_setter(target, clip_rect, clip_rect !=
nullptr);
173 sdl_blit(surf, srcrect, target, &dst);
181 drawingSurface = SDL_CreateRGBSurfaceWithFormat(0, 16, 16, 24, SDL_PIXELFORMAT_BGR888);
186 drawingSurface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_BGR888);
188 fake_interactive =
true;
200 int max_scale = std::min(
209 int def_scale = std::min(
212 scale = std::min(max_scale, def_scale);
214 int min_scale = std::min(
217 scale = std::max(scale, min_scale);
225 if (lsize.x != osize.x / scale || lsize.y != osize.y / scale) {
227 LOG_DP <<
"reducing pixel scale from desired " 229 << scale << std::endl;
231 LOG_DP <<
"pixel scale: " << scale << std::endl;
232 LOG_DP <<
"overriding logical size" << std::endl;
233 LOG_DP <<
" old lsize: " << lsize << std::endl;
234 LOG_DP <<
" old wsize: " << wsize << std::endl;
235 LOG_DP <<
" old osize: " << osize << std::endl;
236 window->set_logical_size(osize.x / scale, osize.y / scale);
237 lsize =
window->get_logical_size();
238 wsize =
window->get_size();
239 osize =
window->get_output_size();
240 LOG_DP <<
" new lsize: " << lsize << std::endl;
241 LOG_DP <<
" new wsize: " << wsize << std::endl;
242 LOG_DP <<
" new osize: " << osize << std::endl;
247 || drawingSurface->w != lsize.x
248 || drawingSurface->h != lsize.y)
251 int bpp = SDL_BITSPERPIXEL(format);
255 LOG_DP <<
"creating " << bpp <<
"bpp drawing surface with format " 256 << SDL_GetPixelFormatName(format) << std::endl;
258 drawingSurface = SDL_CreateRGBSurfaceWithFormat(
268 LOG_DP <<
"destroying old drawing texture" << std::endl;
271 LOG_DP <<
"creating drawing texture" << std::endl;
274 drawingSurface->format->format,
275 SDL_TEXTUREACCESS_STREAMING,
296 uint32_t window_flags = 0;
299 window_flags |= SDL_WINDOW_RESIZABLE;
301 window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
305 window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
307 window_flags |= SDL_WINDOW_MAXIMIZED;
310 uint32_t renderer_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
314 renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
320 std::cerr <<
"Setting mode to " << w <<
"x" << h << std::endl;
324 SDL_DisplayMode currentDisplayMode;
325 SDL_GetCurrentDisplayMode(
window->get_display_index(), ¤tDisplayMode);
326 refresh_rate_ = currentDisplayMode.refresh_rate != 0 ? currentDisplayMode.refresh_rate : 60;
368 return window->get_output_size();
373 return window->get_size();
378 return {0, 0, drawingSurface->w, drawingSurface->h};
384 SDL_Point
p(
window->get_logical_size());
385 return {0, 0,
p.x,
p.y};
390 return drawingSurface->w;
395 return drawingSurface->h;
401 SDL_Delay(milliseconds);
416 if (pitch != drawingSurface->pitch) {
418 throw game::error(
"drawing surface and texture are incompatible");
420 size_t num_bytes = drawingSurface->h * pitch;
421 memcpy(pixels_out, drawingSurface->pixels, num_bytes);
467 window->fill(0, 0, 0, 255);
486 const char*
const drvname = SDL_GetCurrentVideoDriver();
487 return drvname ? drvname :
"<not initialized>";
492 std::vector<std::string> res;
493 int num_drivers = SDL_GetNumVideoDrivers();
495 for(
int n = 0;
n < num_drivers; ++
n) {
496 const char* drvname = SDL_GetVideoDriver(
n);
497 res.emplace_back(drvname ? drvname :
"<invalid driver>");
509 return (
window->get_flags() & flags) != 0;
515 if(
window && SDL_GetDisplayDPI(
window->get_display_index(),
nullptr, &hdpi, &vdpi) == 0) {
525 hdpi /= scale_factor;
526 vdpi /= scale_factor;
529 return { hdpi, vdpi };
533 return { 0.0f, 0.0f };
539 if(dpi.first != 0.0f && dpi.second != 0.0f) {
542 dpi.first *= float(
get_width()) / wsize.x;
544 return { dpi.first / MAGIC_DPI_SCALE_NUMBER, dpi.second / MAGIC_DPI_SCALE_NUMBER };
547 return { 1.0f, 1.0f };
552 std::vector<point> result;
558 const int display_index =
window->get_display_index();
560 const int modes = SDL_GetNumDisplayModes(display_index);
562 std::cerr <<
"No modes supported\n";
576 SDL_GetDisplayBounds(display_index, &bounds);
578 SDL_DisplayMode mode;
580 for(
int i = 0;
i < modes; ++
i) {
581 if(SDL_GetDisplayMode(display_index,
i, &mode) == 0) {
583 if(mode.w > bounds.w && mode.h > bounds.h) {
587 if(mode.w >= min_res.
x && mode.h >= min_res.
y) {
588 result.emplace_back(mode.w, mode.h);
593 if(std::find(result.begin(), result.end(), min_res) == result.end()) {
594 result.push_back(min_res);
597 if(include_current) {
601 std::sort(result.begin(), result.end());
602 result.erase(std::unique(result.begin(), result.end()), result.end());
609 return drawingSurface;
619 return (
window->get_flags() & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0;
631 const color_t color{0, 0, 0, 0xbb};
643 const int border = 5;
688 d->redraw_everything();
715 d->redraw_everything();
719 LOG_DP <<
"updating resolution to " << resolution << std::endl;
732 LOG_DP <<
"updating buffers" << std::endl;
743 d->redraw_everything();
SDL_Texture * drawing_texture_
The drawing texture.
void raise_resize_event()
void set_window_icon(surface &icon)
Sets the icon of the main window.
void _set_fullscreen(bool ison)
int get_height() const
Returns the height of the drawing surface in pixels.
draw_layering(const bool auto_join=true)
SDL_Rect input_area() const
Returns the size and location of the window's input area in pixels.
bool update_locked() const
Whether the screen has been 'locked' or not.
point current_resolution()
static display * get_singleton()
Returns the display object if a display object exists.
const int min_window_height
std::list< events::sdl_handler * > draw_layers
void remove_floating_label(int handle, int fadeout)
removes the floating label given by 'handle' from the screen
void _set_maximized(bool ison)
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::pair< float, float > get_dpi_scale_factor() const
The current scale factor on High-DPI screens.
const int min_window_width
int help_string_
Curent ID of the help string.
const int max_window_width
int get_width() const
Returns the width of the drawing surface in pixels.
void lock_updates(bool value)
Stop the screen being redrawn.
void _set_resolution(const point &res)
static CVideo * singleton_
void update_input_dimensions(int draw_width, int draw_height, int input_width, int input_height)
Update the cached drawing area and input area sizes.
bool non_interactive() const
void set_font_size(int font_size)
void blit_surface(int x, int y, surface surf, SDL_Rect *srcrect=nullptr, SDL_Rect *clip_rect=nullptr)
Copies an area of a surface to the drawing surface.
bool supports_vsync() const
void render_screen()
Renders the screen.
void move_floating_label(int handle, double xmove, double ymove)
moves the floating label given by 'handle' by (xmove,ymove)
SDL_Rect draw_area() const
Returns the size and location of the current drawing area in pixels.
bool set_resolution(const unsigned width, const unsigned height)
void set_window_title(const std::string &title)
Sets the title of the main window.
void initSDL()
Initializes the SDL video subsystem.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
The wrapper class for the SDL_Window class.
void scale(size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, const ScalerCfg &cfg=ScalerCfg(), int yFirst=0, int yLast=std::numeric_limits< int >::max())
void make_test_fake(const unsigned width=1024, const unsigned height=768)
Creates a fake frame buffer for the unit tests.
static std::vector< std::string > enumerate_drivers()
static lg::log_domain log_display("display")
void set_bg_color(const color_t &bg_color)
void set_position(double xpos, double ypos)
map_display and display: classes which take care of displaying the map and game-data on the screen...
sdl::window * get_window()
Returns a pointer to the underlying SDL window.
const int max_pixel_scale
SDL_Point output_size() const
Returns the size of the final render target.
CGFloat get_scale_factor(int display_index)
const int def_window_width
virtual void handle_window_event(const SDL_Event &event)
surface & getDrawingSurface()
Returns a reference to the drawing surface.
SDL_Point window_size() const
Returns the size of the window in display units / screen coordinates.
void init_window()
Initializes a new SDL window instance, taking into account any preiously saved states.
void update_buffers()
Update buffers to match current resolution and pixel scale settings.
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
void set_fullscreen(bool ison)
static std::string current_driver()
SDL_Rect get_floating_label_rect(int handle)
version_info sdl_get_version()
void set_border_size(int border)
Represents version numbers.
int set_help_string(const std::string &str)
Displays a help string with the given text.
const int def_window_height
bool is_fullscreen() const
Base class for all the errors encountered by the engine.
void trigger_full_redraw()
Standard logging facilities (interface).
video_event_handler event_handler_
void clear_all_help_strings()
Removes all help strings.
static void delay(unsigned int milliseconds)
Waits a given number of milliseconds before returning.
void set_window_mode(const MODE_EVENT mode, const point &size)
Sets the window's mode - ie, changing it to fullscreen, maximizing, etc.
Contains a wrapper class for the SDL_Window class.
void update_framebuffer()
Updates and ensures the framebuffer surface is valid.
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
CVideo(const CVideo &)=delete
void clear_screen()
Clear the screen contents.
static map_location::DIRECTION n
std::shared_ptr< halo_record > handle
SDL_Renderer * get_renderer()
Returns a pointer to the underlying window's renderer.
Transitional API for porting SDL_ttf-based code to Pango.
std::vector< point > get_available_resolutions(const bool include_current=false)
Returns the list of available screen resolutions.
const int max_window_height
bool window_has_flags(uint32_t flags) const
Tests whether the given flags are currently set on the SDL window.
virtual void join_global()
std::unique_ptr< sdl::window > window
The SDL window object.
std::pair< float, float > get_dpi() const
The current game screen dpi.
void clear_help_string(int handle)
Removes the help string with the given handle.
int pango_line_width(const std::string &line, int font_size, font::pango_text::FONT_STYLE font_style=font::pango_text::STYLE_NORMAL)
Determine the width of a line of text given a certain font size.