SirVer has proposed merging lp:~widelands-dev/widelands/fix_some_resizing_bugs into lp:widelands.
Requested reviews: Widelands Developers (widelands-dev) Related bugs: Bug #536500 in widelands: "Can not toggle fullscreen with Alt+Enter or resize with w.m." https://bugs.launchpad.net/widelands/+bug/536500 Bug #536559 in widelands: "Fullscreen must not change physical screen resolution" https://bugs.launchpad.net/widelands/+bug/536559 Bug #1203006 in widelands: "Increasing resolution in fullscreen results in the right and bottom sides not being updated properly" https://bugs.launchpad.net/widelands/+bug/1203006 For more details, see: https://code.launchpad.net/~widelands-dev/widelands/fix_some_resizing_bugs/+merge/242593 - Make fullscreen toggle work. Fullscreen is now always at the native resolution so that we do not switch the resolution any more. - Never destroy g_gr. This fixes tons of bugs and makes the surface_cache (nearly) unneeded. It also fixes crashes when switching resolution in the options. -- Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/fix_some_resizing_bugs into lp:widelands.
=== modified file 'src/editor/editorinteractive.cc' --- src/editor/editorinteractive.cc 2014-11-22 10:18:20 +0000 +++ src/editor/editorinteractive.cc 2014-11-23 14:42:44 +0000 @@ -422,7 +422,7 @@ break; case SDLK_f: - g_gr->toggle_fullscreen(); + g_gr->set_fullscreen(!g_gr->fullscreen()); handled = true; break; === modified file 'src/graphic/graphic.cc' --- src/graphic/graphic.cc 2014-11-22 21:31:21 +0000 +++ src/graphic/graphic.cc 2014-11-23 14:42:44 +0000 @@ -46,6 +46,7 @@ #include "io/filesystem/layered_filesystem.h" #include "io/streamwrite.h" #include "logic/roadtype.h" +#include "notifications/notifications.h" #include "ui_basic/progresswindow.h" using namespace std; @@ -58,9 +59,6 @@ /// These are all surfaces that are not loaded from disk. const uint32_t TRANSIENT_SURFACE_CACHE_SIZE = 160 << 20; // shifting converts to MB -constexpr int kFallbackGraphicsWidth = 800; -constexpr int kFallbackGraphicsHeight = 600; - // Sets the icon for the application. void set_icon(SDL_Window* sdl_window) { #ifndef _WIN32 @@ -78,49 +76,30 @@ /** * Initialize the SDL video mode. */ -Graphic::Graphic() - : - m_fallback_settings_in_effect(false), - m_update(true), - surface_cache_(create_surface_cache(TRANSIENT_SURFACE_CACHE_SIZE)), - image_cache_(new ImageCache(surface_cache_.get())), - animation_manager_(new AnimationManager()) +Graphic::Graphic(int window_mode_w, int window_mode_h, bool fullscreen) + : m_window_mode_width(window_mode_w), + m_window_mode_height(window_mode_h), + m_update(true), + surface_cache_(create_surface_cache(TRANSIENT_SURFACE_CACHE_SIZE)), + image_cache_(new ImageCache(surface_cache_.get())), + animation_manager_(new AnimationManager()) { ImageTransformations::initialize(); - m_sdl_window = nullptr; - m_glcontext = nullptr; -} - -void Graphic::initialize(int32_t w, int32_t h, bool fullscreen) { - cleanup(); - // Request an OpenGL 2 context with double buffering. SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - int32_t flags = SDL_WINDOW_OPENGL; - if (fullscreen) { - flags |= SDL_WINDOW_FULLSCREEN; - log("Graphics: Trying FULLSCREEN\n"); - } - - log("Graphics: Try to set Videomode %ux%u\n", w, h); - m_sdl_window = SDL_CreateWindow( - "Widelands Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, flags); - if (!m_sdl_window) { - log("Graphics: Could not set Videomode: %s, trying minimum graphics settings\n", - SDL_GetError()); - flags &= ~SDL_WINDOW_FULLSCREEN; - m_sdl_window = SDL_CreateWindow("Widelands Window", - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - kFallbackGraphicsWidth, kFallbackGraphicsHeight, flags); - m_fallback_settings_in_effect = true; - if (!m_sdl_window) { - throw wexception("Graphics: could not set video mode: %s", SDL_GetError()); - } - } + log("Graphics: Try to set Videomode %ux%u\n", m_window_mode_width, m_window_mode_height); + m_sdl_window = SDL_CreateWindow("Widelands Window", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + m_window_mode_width, + m_window_mode_height, + SDL_WINDOW_OPENGL); + resolution_changed(); + set_fullscreen(fullscreen); SDL_SetWindowTitle(m_sdl_window, ("Widelands " + build_id() + '(' + build_type() + ')').c_str()); set_icon(m_sdl_window); @@ -162,8 +141,6 @@ SDL_GL_SwapWindow(m_sdl_window); - screen_.reset(new GLSurfaceScreen(w, h)); - /* Information about the video capabilities. */ { SDL_DisplayMode disp_mode; @@ -180,18 +157,12 @@ assert(SDL_BYTESPERPIXEL(disp_mode.format) == 4); } - m_rendertarget.reset(new RenderTarget(screen_.get())); - pic_road_normal_.reset(load_image("world/pics/roadt_normal.png")); pic_road_busy_.reset(load_image("world/pics/roadt_busy.png")); } -bool Graphic::check_fallback_settings_in_effect() +Graphic::~Graphic() { - return m_fallback_settings_in_effect; -} - -void Graphic::cleanup() { m_maptextures.clear(); surface_cache_->flush(); // TODO(unknown): this should really not be needed, but currently is :( @@ -208,15 +179,10 @@ } } -Graphic::~Graphic() -{ - cleanup(); -} - /** * Return the screen x resolution */ -int32_t Graphic::get_xres() +int Graphic::get_xres() { return screen_->width(); } @@ -224,14 +190,31 @@ /** * Return the screen x resolution */ -int32_t Graphic::get_yres() +int Graphic::get_yres() { return screen_->height(); } -bool Graphic::is_fullscreen() -{ - return SDL_GetWindowFlags(m_sdl_window) & SDL_WINDOW_FULLSCREEN; +void Graphic::change_resolution(int w, int h) { + m_window_mode_width = w; + m_window_mode_height = h; + + if (!fullscreen()) { + SDL_SetWindowSize(m_sdl_window, w, h); + resolution_changed(); + } +} + +void Graphic::resolution_changed() { + int new_w, new_h; + SDL_GetWindowSize(m_sdl_window, &new_w, &new_h); + + screen_.reset(new GLSurfaceScreen(new_w, new_h)); + m_rendertarget.reset(new RenderTarget(screen_.get())); + + Notifications::publish(GraphicResolutionChanged{new_w, new_h}); + + update(); } /** @@ -240,27 +223,39 @@ RenderTarget * Graphic::get_render_target() { m_rendertarget->reset(); - return m_rendertarget.get(); } -/** - * Switch from fullscreen to windowed mode or vice-versa -*/ -void Graphic::toggle_fullscreen() -{ - // TODO(unknown): implement proper fullscreening here. The way it can work is to - // recreate SurfaceCache but keeping ImageCache around. Then exiting and - // reinitalizing the SDL Video Mode should just work: all surface are - // recreated dynamically and correctly. - // Note: Not all Images are cached in the ImageCache, at time of me writing - // this, only InMemoryImage does not safe itself in the ImageCache. And this - // should only be a problem for Images loaded from maps. - if (SDL_GetWindowFlags(m_sdl_window) & SDL_WINDOW_FULLSCREEN) { +bool Graphic::fullscreen() +{ + uint32_t flags = SDL_GetWindowFlags(m_sdl_window); + return (flags & SDL_WINDOW_FULLSCREEN) || (flags & SDL_WINDOW_FULLSCREEN_DESKTOP); +} + +void Graphic::set_fullscreen(const bool value) +{ + if (value == fullscreen()) { + return; + } + + // Widelands is not resolution agnostic, so when we set fullscreen, we want + // it at the full resolution of the desktop and we want to know about the + // true resolution (SDL supports hiding the true resolution from the + // application). Since SDL ignores requests to change the size of the window + // whet fullscreen, we do it when in windowed mode. + if (value) { + SDL_DisplayMode display_mode; + SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(m_sdl_window), &display_mode); + SDL_SetWindowSize(m_sdl_window, display_mode.w, display_mode.h); + + SDL_SetWindowFullscreen(m_sdl_window, SDL_WINDOW_FULLSCREEN_DESKTOP); + } else { SDL_SetWindowFullscreen(m_sdl_window, 0); - } else { - SDL_SetWindowFullscreen(m_sdl_window, SDL_WINDOW_FULLSCREEN); + + // Next line does not work. See comment in refresh(). + SDL_SetWindowSize(m_sdl_window, m_window_mode_width, m_window_mode_height); } + resolution_changed(); } @@ -283,6 +278,17 @@ */ void Graphic::refresh() { + // Setting the window size immediately after going out of fullscreen does + // not work properly. We work around this issue by resizing the window in + // refresh() when in window mode. + if (!fullscreen()) { + int true_width, true_height; + SDL_GetWindowSize(m_sdl_window, &true_width, &true_height); + if (true_width != m_window_mode_width || true_height != m_window_mode_height) { + SDL_SetWindowSize(m_sdl_window, m_window_mode_width, m_window_mode_height); + } + } + SDL_GL_SwapWindow(m_sdl_window); m_update = false; } === modified file 'src/graphic/graphic.h' --- src/graphic/graphic.h 2014-11-22 18:36:33 +0000 +++ src/graphic/graphic.h 2014-11-23 14:42:44 +0000 @@ -28,6 +28,8 @@ #include "base/rect.h" #include "graphic/image_cache.h" +#include "notifications/notifications.h" +#include "notifications/note_ids.h" #define MAX_RECTS 20 @@ -38,6 +40,15 @@ class StreamWrite; struct Texture; +// Will be send whenever the resolution changes. +struct GraphicResolutionChanged { + CAN_BE_SEND_AS_NOTE(NoteId::GraphicResolutionChanged) + + // New width and height in pixels. + int width; + int height; +}; + /** * This class is a kind of Swiss Army knife for your graphics need. It * initializes the graphic system and provides access to resolutions. It has an @@ -46,18 +57,21 @@ */ class Graphic { public: - Graphic(); + // Creates a new graphic mode with the given resolution if fullscreen is + // false, otherwise a window that fills the screen. + Graphic(int window_mode_w, int window_mode_height, bool fullscreen); ~Graphic(); - // Initialize or reinitialize the graphics system. Throws on error. - void initialize(int32_t w, int32_t h, bool fullscreen); + // Gets and sets the resolution. + void change_resolution(int w, int h); + int get_xres(); + int get_yres(); - int32_t get_xres(); - int32_t get_yres(); - bool is_fullscreen(); + // Changes the window to be fullscreen or not. + bool fullscreen(); + void set_fullscreen(bool); RenderTarget * get_render_target(); - void toggle_fullscreen(); void update(); bool need_update() const; void refresh(); @@ -79,12 +93,13 @@ Surface& get_road_texture(int32_t roadtex); - bool check_fallback_settings_in_effect(); - private: - void cleanup(); + // Called when the resolution (might) have changed. + void resolution_changed(); - bool m_fallback_settings_in_effect; + // The height & width of the window should we be in window mode. + int m_window_mode_width; + int m_window_mode_height; /// This is the main screen Surface. /// A RenderTarget for this can be retrieved with get_render_target() === modified file 'src/graphic/text/test/render_richtext.cc' --- src/graphic/text/test/render_richtext.cc 2014-11-23 10:13:14 +0000 +++ src/graphic/text/test/render_richtext.cc 2014-11-23 14:42:44 +0000 @@ -98,8 +98,7 @@ g_fs = new LayeredFileSystem(); g_fs->add_file_system(&FileSystem::create(INSTALL_DATADIR)); - g_gr = new Graphic(); - g_gr->initialize(1, 1, false); + g_gr = new Graphic(1, 1, false); } } // namespace === modified file 'src/logic/map_info.cc' --- src/logic/map_info.cc 2014-11-22 21:31:21 +0000 +++ src/logic/map_info.cc 2014-11-23 14:42:44 +0000 @@ -49,8 +49,7 @@ g_fs = new LayeredFileSystem(); g_fs->add_file_system(&FileSystem::create(INSTALL_DATADIR)); - g_gr = new Graphic(); - g_gr->initialize(1, 1, false); + g_gr = new Graphic(1, 1, false); } } // namespace === modified file 'src/logic/ware_descr.cc' --- src/logic/ware_descr.cc 2014-09-10 08:55:04 +0000 +++ src/logic/ware_descr.cc 2014-11-23 14:42:44 +0000 @@ -36,7 +36,7 @@ m_tribe (gtribe), m_helptext (global_s.get_string("help", "")), m_icon_fname (directory + "/menu.png"), - m_icon(g_gr ? g_gr->images().get("pics/but0.png") : nullptr) // because of dedicated + m_icon(g_gr->images().get("pics/but0.png")) { m_default_target_quantity = global_s.get_positive("default_target_quantity", std::numeric_limits<uint32_t>::max()); === modified file 'src/notifications/note_ids.h' --- src/notifications/note_ids.h 2014-09-10 19:54:01 +0000 +++ src/notifications/note_ids.h 2014-11-23 14:42:44 +0000 @@ -32,6 +32,8 @@ FieldPossession, FieldTransformed, ProductionSiteOutOfResources, + + GraphicResolutionChanged, }; #endif // end of include guard: WL_NOTIFICATIONS_NOTE_IDS_H === modified file 'src/wlapplication.cc' --- src/wlapplication.cc 2014-11-22 18:36:33 +0000 +++ src/wlapplication.cc 2014-11-23 14:42:44 +0000 @@ -244,7 +244,6 @@ m_homedir = m_commandline["homedir"]; m_commandline.erase("homedir"); } - bool dedicated = m_commandline.count("dedicated"); #ifdef REDIRECT_OUTPUT if (!redirect_output()) redirect_output(m_homedir); @@ -259,18 +258,15 @@ init_language(); // search paths must already be set up cleanup_replays(); - if (!dedicated) { - // handling of graphics - init_hardware(); - - if (TTF_Init() == -1) - throw wexception - ("True Type library did not initialize: %s\n", TTF_GetError()); - - UI::g_fh = new UI::FontHandler(); - UI::g_fh1 = UI::create_fonthandler(g_gr); - } else - g_gr = nullptr; + // handling of graphics + init_hardware(); + + if (TTF_Init() == -1) + throw wexception + ("True Type library did not initialize: %s\n", TTF_GetError()); + + UI::g_fh = new UI::FontHandler(); + UI::g_fh1 = UI::create_fonthandler(g_gr); if (SDLNet_Init() == -1) throw wexception("SDLNet_Init failed: %s\n", SDLNet_GetError()); @@ -440,9 +436,6 @@ g_sound_handler.change_music("menu", 1000); mainmenu(); - - delete g_gr; - g_gr = nullptr; } g_sound_handler.stop_music(500); @@ -671,38 +664,14 @@ } } -/** - * Initialize the graphics subsystem (or shutdown, if w and h are 0) - * with the given resolution. - * Throws an exception on failure. - */ -void WLApplication::init_graphics(int32_t w, int32_t h, bool fullscreen) -{ - if (!w && !h) { // shutdown. - delete g_gr; - g_gr = nullptr; - return; - } - assert(w > 0 && h > 0); - - if (!g_gr) { - g_gr = new Graphic(); - g_gr->initialize(w, h, fullscreen); - } else { - if (g_gr->get_xres() != w || g_gr->get_yres() != h || g_gr->is_fullscreen() != fullscreen) { - g_gr->initialize(w, h, fullscreen); - } - } -} - void WLApplication::refresh_graphics() { Section & s = g_options.pull_section("global"); - // Switch to the new graphics system now, if necessary. - init_graphics(s.get_int("xres", DEFAULT_RESOLUTION_W), - s.get_int("yres", DEFAULT_RESOLUTION_H), - s.get_bool("fullscreen", false)); + g_gr->change_resolution( + s.get_int("xres", DEFAULT_RESOLUTION_W), s.get_int("yres", DEFAULT_RESOLUTION_H)); + g_gr->set_fullscreen(s.get_bool("fullscreen", false)); + // does only work with a window set_input_grab(s.get_bool("inputgrab", false)); } @@ -827,7 +796,9 @@ SDL_ShowCursor(SDL_DISABLE); - refresh_graphics(); + g_gr = new Graphic(s.get_int("xres", DEFAULT_RESOLUTION_W), + s.get_int("yres", DEFAULT_RESOLUTION_H), + s.get_bool("fullscreen", false)); // Start the audio subsystem // must know the locale before calling this! @@ -838,14 +809,9 @@ void WLApplication::shutdown_hardware() { - if (g_gr) - wout - << - "WARNING: Hardware shutting down although graphics system is still " - "alive!" - << std::endl; + delete g_gr; + g_gr = nullptr; - init_graphics(0, 0, false); SDL_QuitSubSystem(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK); #ifndef _WIN32 @@ -1049,14 +1015,6 @@ std::string messagetitle; std::string message; - if (g_gr->check_fallback_settings_in_effect()) - { - messagetitle = "Fallback settings in effect"; - message = _ - ("Your video settings could not be enabled, and fallback settings are in effect. " - "Please check the graphics options!"); - } - for (;;) { // Refresh graphics system in case we just changed resolution. refresh_graphics(); === modified file 'src/wlapplication.h' --- src/wlapplication.h 2014-11-22 18:36:33 +0000 +++ src/wlapplication.h 2014-11-23 14:42:44 +0000 @@ -164,13 +164,8 @@ void set_mouse_lock(const bool locked) {m_mouse_locked = locked;} //@} - void init_graphics(int32_t w, int32_t h, bool fullscreen); - /** - * Refresh the graphics from the latest options. - * - * \note See caveats for \ref init_graphics() - */ + // Refresh the graphics settings with the latest options. void refresh_graphics(); void handle_input(InputCallback const *); === modified file 'src/wui/interactive_base.cc' --- src/wui/interactive_base.cc 2014-11-22 10:18:20 +0000 +++ src/wui/interactive_base.cc 2014-11-23 14:42:44 +0000 @@ -79,12 +79,7 @@ }; InteractiveBase::InteractiveBase(EditorGameBase& the_egbase, Section& global_s) - : MapView(nullptr, - 0, - 0, - global_s.get_int("xres", DEFAULT_RESOLUTION_W), - global_s.get_int("yres", DEFAULT_RESOLUTION_H), - *this), + : MapView(nullptr, 0, 0, g_gr->get_xres(), g_gr->get_yres(), *this), // Initialize chatoveraly before the toolbar so it is below m_show_workarea_preview(global_s.get_bool("workareapreview", true)), m_chatOverlay(new ChatOverlay(this, 10, 25, get_w() / 2, get_h() - 25)), @@ -107,10 +102,19 @@ m_label_speed(this, get_w(), 1, std::string(), UI::Align_TopRight), unique_window_handler_(new UniqueWindowHandler()), // Start at idx 0 for 2 enhancements, idx 3 for 1, idx 5 if none - m_workarea_pics - {g_gr->images().get("pics/workarea123.png"), g_gr->images().get("pics/workarea23.png"), - g_gr->images().get("pics/workarea3.png"), g_gr->images().get("pics/workarea12.png"), - g_gr->images().get("pics/workarea2.png"), g_gr->images().get("pics/workarea1.png")} { + m_workarea_pics{g_gr->images().get("pics/workarea123.png"), + g_gr->images().get("pics/workarea23.png"), + g_gr->images().get("pics/workarea3.png"), + g_gr->images().get("pics/workarea12.png"), + g_gr->images().get("pics/workarea2.png"), + g_gr->images().get("pics/workarea1.png")} { + + graphic_resolution_changed_subscriber_ = Notifications::subscribe<GraphicResolutionChanged>( + [this](const GraphicResolutionChanged& message) { + set_size(message.width, message.height); + adjust_toolbar_position(); + }); + m_toolbar.set_layout_toplevel(true); m->quicknavigation->set_setview (boost::bind(&MapView::set_viewpoint, this, _1, true)); === modified file 'src/wui/interactive_base.h' --- src/wui/interactive_base.h 2014-10-14 06:30:20 +0000 +++ src/wui/interactive_base.h 2014-11-23 14:42:44 +0000 @@ -24,15 +24,17 @@ #include <SDL_keycode.h> +#include "graphic/graphic.h" #include "logic/editor_game_base.h" #include "logic/map.h" +#include "notifications/notifications.h" +#include "ui_basic/box.h" +#include "ui_basic/textarea.h" +#include "ui_basic/unique_window.h" #include "wui/chatoverlay.h" #include "wui/debugconsole.h" #include "wui/mapview.h" #include "wui/overlay_manager.h" -#include "ui_basic/box.h" -#include "ui_basic/textarea.h" -#include "ui_basic/unique_window.h" namespace Widelands {struct CoordPath;} @@ -179,6 +181,9 @@ } m_sel; std::unique_ptr<InteractiveBaseInternals> m; + + std::unique_ptr<Notifications::Subscriber<GraphicResolutionChanged>> + graphic_resolution_changed_subscriber_; Widelands::EditorGameBase & m_egbase; uint32_t m_display_flags; uint32_t m_lastframe; // system time (milliseconds) === modified file 'src/wui/interactive_player.cc' --- src/wui/interactive_player.cc 2014-11-22 10:18:20 +0000 +++ src/wui/interactive_player.cc 2014-11-23 14:42:44 +0000 @@ -402,7 +402,7 @@ return true; case SDLK_f: - g_gr->toggle_fullscreen(); + g_gr->set_fullscreen(!g_gr->fullscreen()); return true; case SDLK_KP_7: === modified file 'src/wui/interactive_spectator.cc' --- src/wui/interactive_spectator.cc 2014-11-22 10:18:20 +0000 +++ src/wui/interactive_spectator.cc 2014-11-23 14:42:44 +0000 @@ -264,7 +264,7 @@ return true; case SDLK_f: - g_gr->toggle_fullscreen(); + g_gr->set_fullscreen(!g_gr->fullscreen()); return true; case SDLK_RETURN:
_______________________________________________ Mailing list: https://launchpad.net/~widelands-dev Post to : widelands-dev@lists.launchpad.net Unsubscribe : https://launchpad.net/~widelands-dev More help : https://help.launchpad.net/ListHelp