Mercurial > fife-parpg
changeset 654:5d6b1820b953
* Added the ability to change screen modes on the fly. This works both in OpenGL and SDL modes.
* Added IEngineChangeListener so the client can update the cameras viewport if the screen mode has been changed. I chose to do it this way because the engine has no way to know which camera it should update. It will be up to the client to do it.
* The cursor surface is now correctly freed when exiting.
* Added DeviceCaps::getNearestScreenMode() for the client to request a supported screen mode.
closes[t:315]
line wrap: on
line diff
--- a/engine/core/controller/engine.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/controller/engine.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -74,6 +74,8 @@ #include "view/renderers/cellselectionrenderer.h" #include "view/renderers/blockinginforenderer.h" #include "view/renderers/genericrenderer.h" +#include "video/image.h" +#include "gui/console/console.h" #include "engine.h" #ifdef USE_COCOA @@ -105,7 +107,8 @@ m_logmanager(0), m_cursor(0), m_settings(), - m_devcaps(){ + m_devcaps(), + m_changelisteners() { #ifdef USE_COCOA // The next lines ensure that Cocoa is initialzed correctly. // This is needed for SDL to function properly on MAC OS X. @@ -131,6 +134,26 @@ return m_devcaps; } + Image* Engine::changeScreenMode(const ScreenMode& mode){ + m_cursor->invalidate(); + m_imagepool->invalidateLoadedImages(); + m_defaultfont->invalidate(); + m_guimanager->invalidateFonts(); + + Image* screen = m_renderbackend->setScreenMode(mode); + + m_guimanager->resizeTopContainer(0,0,mode.getWidth(), mode.getHeight()); + m_guimanager->getConsole()->reLayout(); + + std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin(); + while (i != m_changelisteners.end()) { + (*i)->onScreenModeChanged(mode); + ++i; + } + + return screen; + } + void Engine::preInit() { m_logmanager = LogManager::instance(); @@ -248,7 +271,7 @@ m_settings.getDefaultFontSize(), m_settings.getDefaultFontGlyphs()); FL_LOG(_log, "Initializing GUI manager"); - m_guimanager->init(m_gui_graphics, m_settings.getScreenWidth(), m_settings.getScreenHeight()); + m_guimanager->init(m_gui_graphics, m_renderbackend->getScreenWidth(), m_renderbackend->getScreenHeight()); FL_LOG(_log, "GUI manager initialized"); SDL_EnableUNICODE(1); @@ -343,6 +366,21 @@ void Engine::finalizePumping() { // nothing here at the moment.. } + + void Engine::addChangeListener(IEngineChangeListener* listener) { + m_changelisteners.push_back(listener); + } + + void Engine::removeChangeListener(IEngineChangeListener* listener) { + std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin(); + while (i != m_changelisteners.end()) { + if ((*i) == listener) { + m_changelisteners.erase(i); + return; + } + ++i; + } + } }//FIFE /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */
--- a/engine/core/controller/engine.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/controller/engine.h Thu Oct 21 18:50:50 2010 +0000 @@ -63,6 +63,17 @@ class Cursor; class SoundClipPool; class RendererBase; + class Image; + + + class IEngineChangeListener { + public: + virtual ~IEngineChangeListener() {} + + /** Screen mode has been changed + */ + virtual void onScreenModeChanged(const ScreenMode& newmode) = 0; + }; /** Engine acts as a controller to the whole system * Responsibilities of the engine are: @@ -88,6 +99,16 @@ */ const DeviceCaps& getDeviceCaps() const; + /** Changes the screen mode. + * This should be called instead of the renderer's setScreenMode() function. + * It takes care of any objects that need to be re-created after switching + * screen modes. + * + * @param mode A valid ScreenMode retrieved from FIFE::DeviceCaps::getNearestScreenMode() + * @return The new Screen Image + */ + Image* changeScreenMode(const ScreenMode& mode); + /** Initializes the engine */ void init(); @@ -163,6 +184,16 @@ */ Cursor* getCursor() const { return m_cursor; } + /** Adds new change listener + * @param listener to add + */ + void addChangeListener(IEngineChangeListener* listener); + + /** Removes associated change listener + * @param listener to remove + */ + void removeChangeListener(IEngineChangeListener* listener); + private: void preInit(); @@ -189,6 +220,8 @@ std::vector<RendererBase*> m_renderers; + std::vector<IEngineChangeListener*> m_changelisteners; + #ifdef USE_COCOA objc_object *m_autoreleasePool; #endif
--- a/engine/core/controller/engine.i Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/controller/engine.i Thu Oct 21 18:50:50 2010 +0000 @@ -41,6 +41,7 @@ class RendererBase; class DeviceCaps; class ScreenMode; + class Image; class EngineSettings { public: @@ -85,6 +86,13 @@ EngineSettings(); }; + %feature("director") IEngineChangeListener; + class IEngineChangeListener { + public: + virtual ~IEngineChangeListener() {} + virtual void onScreenModeChanged(const ScreenMode& newmode) = 0; + }; + class Engine { public: Engine(); @@ -96,6 +104,8 @@ EngineSettings& getSettings(); const DeviceCaps& getDeviceCaps() const; + Image* changeScreenMode(const ScreenMode& mode); + void init(); void destroy(); @@ -112,5 +122,8 @@ GuiFont* getDefaultFont(); VFS* getVFS(); Cursor* getCursor(); + + void addChangeListener(IEngineChangeListener* listener); + void removeChangeListener(IEngineChangeListener* listener); }; }
--- a/engine/core/gui/base/gui_font.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/gui/base/gui_font.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -38,15 +38,15 @@ GuiFont::GuiFont(AbstractFont* font): m_font(font) { assert(font); } - + GuiFont::~GuiFont() { delete m_font; } - + int GuiFont::getStringIndexAt(const std::string& text, int x) const { return m_font->getStringIndexAt(text, x); } - + void GuiFont::drawString(gcn::Graphics* graphics, const std::string& text, int x, int y) { if (text == "") { return; @@ -90,35 +90,35 @@ } image->render(rect); } - + void GuiFont::setRowSpacing (int spacing) { m_font->setRowSpacing(spacing); } - + int GuiFont::getRowSpacing() const { return m_font->getRowSpacing(); } - + void GuiFont::setGlyphSpacing(int spacing) { m_font->setGlyphSpacing(spacing); } - + int GuiFont::getGlyphSpacing() const { return m_font->getGlyphSpacing(); } - + void GuiFont::setAntiAlias(bool antiAlias) { m_font->setAntiAlias(antiAlias); } - + bool GuiFont::isAntiAlias() { return m_font->isAntiAlias(); } - + Image* GuiFont::getAsImage(const std::string& text) { return m_font->getAsImage(text); } - + Image* GuiFont::getAsImageMultiline(const std::string& text) { return m_font->getAsImageMultiline(text); } @@ -130,16 +130,20 @@ void GuiFont::setColor(uint8_t r,uint8_t g,uint8_t b, uint8_t a) { m_font->setColor(r, g, b, a); } - + SDL_Color GuiFont::getColor() const { return m_font->getColor(); } - + int GuiFont::getWidth(const std::string& text) const { return m_font->getWidth(text); } - + int GuiFont::getHeight() const { return m_font->getHeight(); } + + void GuiFont::invalidate() { + m_font->invalidate(); + } }
--- a/engine/core/gui/base/gui_font.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/gui/base/gui_font.h Thu Oct 21 18:50:50 2010 +0000 @@ -43,7 +43,7 @@ */ GuiFont(AbstractFont* font); virtual ~GuiFont(); - + int getStringIndexAt(const std::string& text, int x) const; void drawString(gcn::Graphics* graphics, const std::string& text, int x, int y); void drawMultiLineString(gcn::Graphics* graphics, const std::string& text, int x, int y); @@ -61,7 +61,8 @@ SDL_Color getColor() const; int getWidth(const std::string& text) const; int getHeight() const; - + void invalidate(); + private: AbstractFont* m_font; };
--- a/engine/core/gui/guimanager.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/gui/guimanager.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -205,6 +205,14 @@ } } + void GUIManager::invalidateFonts() { + std::vector<GuiFont*>::iterator it = m_fonts.begin(); + while (it != m_fonts.end()) { + (*it)->invalidate(); + ++it; + } + } + GuiFont* GUIManager::setDefaultFont(const std::string& path, unsigned int size, const std::string& glyphs) { m_fontpath = path; m_fontsize = size;
--- a/engine/core/gui/guimanager.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/gui/guimanager.h Thu Oct 21 18:50:50 2010 +0000 @@ -62,8 +62,8 @@ * * This class controls the GUI system in FIFE. */ - class GUIManager : - public DynamicSingleton<GUIManager>, + class GUIManager : + public DynamicSingleton<GUIManager>, public ISdlEventListener { public: @@ -85,14 +85,14 @@ * This will be called each frame. */ void turn(); - + /** Inits the GUI Manager. * @param graphics backend specific grapchics object to use * @param screenWidth width for the gui top container * @param screenHeight height for the gui top container */ void init(gcn::Graphics* graphics, int screenWidth, int screenHeight); - + /** Resizes the top container. * * @param x The new starting X coordinate. @@ -101,7 +101,7 @@ * @param height The new height. */ void resizeTopContainer(unsigned int x, unsigned int y, unsigned int width, unsigned int height); - + /** Adds a new widget. * * @param A pointer to the widget to add. @@ -117,7 +117,7 @@ * @return The top container. */ gcn::Container* getTopContainer() const { return m_gcn_topcontainer; } - + /** Gets the console. * * @return The console. @@ -127,7 +127,7 @@ /** Set the global font properties. */ GuiFont* setDefaultFont(const std::string& path, unsigned int size, const std::string& glyphs); - + /** Gets font with given properties. Note that font will be owned by guimanager */ GuiFont* createFont(const std::string& path = "", unsigned int size = 0, const std::string& glyphs = ""); @@ -136,6 +136,8 @@ */ void releaseFont(GuiFont* font); + void invalidateFonts(); + bool onSdlEvent(SDL_Event& evt); KeyEvent translateKeyEvent(const gcn::KeyEvent& evt); @@ -172,7 +174,7 @@ std::string m_fontpath; std::string m_fontglyphs; int m_fontsize; - + // true, if guichan logic has already been executed for this round bool m_logic_executed; };
--- a/engine/core/util/resource/pool.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/util/resource/pool.h Thu Oct 21 18:50:50 2010 +0000 @@ -134,7 +134,7 @@ */ virtual void reset(); - private: + protected: class PoolEntry { public: PoolEntry(): resource(0), location(0), loader(0) {}
--- a/engine/core/video/cursor.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/cursor.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -89,11 +89,12 @@ m_drag_offset_y(0), m_mx(0), m_my(0), - m_timemanager(TimeManager::instance()) { + m_timemanager(TimeManager::instance()), + m_invalidated(false) { assert(m_timemanager); set(m_cursor_type, m_cursor_id); } - + void Cursor::set(MouseCursorType ctype, unsigned int cursor_id) { m_cursor_id = cursor_id; m_cursor_type = ctype; @@ -115,8 +116,9 @@ m_animtime = m_timemanager->getTime(); } } + m_invalidated = false; } - + void Cursor::setDrag(MouseCursorType ctype, unsigned int drag_id, int drag_offset_x, int drag_offset_y) { m_drag_type = ctype; m_drag_id = drag_id; @@ -128,13 +130,28 @@ } } } - + + void Cursor::invalidate() { + if (m_native_cursor != NULL) { + SDL_free(m_native_cursor->wm_cursor); + m_native_cursor->wm_cursor = NULL; + SDL_FreeCursor(m_native_cursor); + m_native_cursor = NULL; + + m_invalidated = true; + } + } + void Cursor::draw() { + if (m_invalidated) { + set(m_cursor_type, m_cursor_id); + } + SDL_GetMouseState(&m_mx, &m_my); if ((m_cursor_type == CURSOR_NATIVE) && (m_drag_type == CURSOR_NONE)) { return; } - + // render possible drag image Image* img = NULL; if (m_drag_type == CURSOR_IMAGE) { @@ -150,7 +167,7 @@ img->render(area); m_renderbackend->popClipArea(); } - + // render possible cursor image img = NULL; if (m_cursor_type == CURSOR_IMAGE) { @@ -324,7 +341,7 @@ cursor->x_cursor = xCursor; XSync(dsp, false); #endif - + m_native_cursor = curs2; SDL_SetCursor(curs2);
--- a/engine/core/video/cursor.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/cursor.h Thu Oct 21 18:50:50 2010 +0000 @@ -39,7 +39,7 @@ class AnimationPool; class RenderBackend; class TimeManager; - + /** Defines the type of shown cursor * native -> default cursor * image -> cursor from image pool @@ -65,13 +65,13 @@ NC_CROSS, // Crosshair NC_UPARROW, // Vertical arrow NC_RESIZENW, // Cursor for resize in northwest corner - NC_RESIZESE, // - NC_RESIZESW, // - NC_RESIZENE, // - NC_RESIZEE, // - NC_RESIZEW, // - NC_RESIZEN, // - NC_RESIZES, // + NC_RESIZESE, // + NC_RESIZESW, // + NC_RESIZENE, // + NC_RESIZEE, // + NC_RESIZEW, // + NC_RESIZEN, // + NC_RESIZES, // NC_RESIZEALL, // Four-pointed arrow pointing north, south, east, and west NC_NO, // Slashed circle NC_HAND, // Hand. Common for links, etc. @@ -89,7 +89,9 @@ /** Destructor. */ - virtual ~Cursor() {} + virtual ~Cursor() { invalidate(); } + + void invalidate(); /** draws cursor on screen */ @@ -100,26 +102,26 @@ * @param cursor_id Pool id to image or animation. For native cursors, this is the resource id to native cursor, or one of the values in NativeCursor */ void set(MouseCursorType ctype, unsigned int cursor_id=0); - + /** Sets the current drag cursor type and pool value * @param ctype drag cursor type * @param drag_id pool id for the drag cursor (either image or animation) * @param drag_offset offset of drag image shown with cursor */ void setDrag(MouseCursorType ctype, unsigned int drag_id=0, int drag_offset_x=0, int drag_offset_y=0); - + /** Gets the current mouse cursor type */ MouseCursorType getType() const { return m_cursor_type; } - + /** Gets the current mouse cursor pool id */ unsigned int getId() const { return m_cursor_id; } - + /** Gets the current mouse cursor type */ MouseCursorType getDragType() const { return m_drag_type; } - + /** Gets the current mouse cursor pool id */ unsigned int getDragId() const { return m_drag_id; } @@ -146,7 +148,7 @@ * @param One of the values in NativeCursor */ unsigned int getNativeId(unsigned int cursor_id); - + private: unsigned int m_cursor_id; unsigned int m_drag_id; @@ -154,19 +156,21 @@ MouseCursorType m_drag_type; SDL_Cursor* m_native_cursor; - + RenderBackend* m_renderbackend; ImagePool* m_imgpool; AnimationPool* m_animpool; - + unsigned int m_animtime; unsigned int m_drag_animtime; - + int m_drag_offset_x; int m_drag_offset_y; int m_mx; int m_my; TimeManager* m_timemanager; + + bool m_invalidated; }; } //FIFE
--- a/engine/core/video/devicecaps.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/devicecaps.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -53,24 +53,37 @@ } bool ScreenMode::operator <(const ScreenMode& rhs) const { - if (m_bpp < rhs.getBPP() ) { + + //sort by fullscreen first + if (!isFullScreen() && rhs.isFullScreen()){ + return true; + } + else if (isFullScreen() && !rhs.isFullScreen()){ + return false; + } + + //next by bpp + if (m_bpp < rhs.getBPP()){ + return true; + } + else if (m_bpp > rhs.getBPP()){ + return false; + } + + //then by screen dimentions + if (m_width == rhs.getWidth() && m_height == rhs.getHeight()){ + if (!(m_SDLFlags & SDL_HWSURFACE) && (rhs.getSDLFlags() & SDL_HWSURFACE)) { + //I would like return true so that we prefer hardware surfaces but + //it really slows the engine down in fullscreen. See the SDL FAQ for an + //explanation. + return false; + } + } + + else if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) { return true; } - else if (m_bpp == rhs.getBPP()) { - if (m_width == rhs.getWidth() && m_height == rhs.getHeight()){ - if (!(m_SDLFlags & SDL_HWSURFACE) && (rhs.getSDLFlags() & SDL_HWSURFACE)) { - //I would like return true so that we prefer hardware surfaces but - //it really slows the engine down in fullscreen. See the SDL FAQ for an - //explanation. - return false; - } - } - - else if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) { - return true; - } - } return false; }
--- a/engine/core/video/fonts/abstractfont.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/fonts/abstractfont.h Thu Oct 21 18:50:50 2010 +0000 @@ -99,7 +99,7 @@ * The rsulting image is pooled, so it's not that time critical */ virtual Image* getAsImageMultiline(const std::string& text) = 0; - + virtual std::string splitTextToWidth (const std::string& text, int render_width) = 0; /** Set the color the text should be rendered in @@ -109,14 +109,16 @@ /** Get the color the text was rendered in */ virtual SDL_Color getColor() const = 0; - + /** gets width of given text */ virtual int getWidth(const std::string& text) const = 0; - + /** gets height of this font */ virtual int getHeight() const = 0; + + virtual void invalidate() = 0; }; }
--- a/engine/core/video/fonts/fontbase.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/fonts/fontbase.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -50,6 +50,10 @@ m_antiAlias(true) { } + void FontBase::invalidate() { + m_pool.invalidateCachedText(); + } + void FontBase::setRowSpacing(int spacing) { mRowSpacing = spacing; } @@ -143,7 +147,7 @@ } lines.push_back(text_surface); } while (it != text.end()); - + render_height = (getRowSpacing() + getHeight()) * lines.size(); SDL_Surface* final_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, render_width,render_height,32, @@ -173,7 +177,7 @@ const uint8_t newline_utf8 = '\n'; uint32_t newline; utf8::utf8to32(&newline_utf8,&newline_utf8 + 1,&newline); - if (render_width <= 0 || text.empty()) { + if (render_width <= 0 || text.empty()) { return text; } std::string output; @@ -190,7 +194,7 @@ } else { firstLine = false; } - + bool haveNewLine = false; while( getWidth(line) < render_width && pos != text.end() ) { @@ -223,7 +227,7 @@ output.append(line); continue; } - + if (line == "\n") { ++pos; }
--- a/engine/core/video/fonts/fontbase.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/fonts/fontbase.h Thu Oct 21 18:50:50 2010 +0000 @@ -48,7 +48,9 @@ class FontBase: public AbstractFont { public: FontBase(); - virtual ~FontBase() {} + virtual ~FontBase() {}; + + void invalidate(); void setRowSpacing (int spacing); int getRowSpacing() const; void setGlyphSpacing(int spacing); @@ -56,15 +58,15 @@ void setAntiAlias(bool antiAlias); bool isAntiAlias(); virtual int getStringIndexAt(const std::string &text, int x) const; - + Image* getAsImage(const std::string& text); Image* getAsImageMultiline(const std::string& text); std::string splitTextToWidth (const std::string& text, int render_width); SDL_Color getColor() const; - - virtual SDL_Surface* renderString(const std::string& text) = 0; - + + virtual SDL_Surface* renderString(const std::string& text) = 0; + protected: TextRenderPool m_pool;
--- a/engine/core/video/fonts/textrenderpool.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/fonts/textrenderpool.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -130,4 +130,12 @@ if( m_poolSize == 0 ) m_collectTimer.stop(); } + + void TextRenderPool::invalidateCachedText() { + type_pool::iterator it = m_pool.begin(); + while (it != m_pool.end()) { + it->image->invalidate(); + ++it; + } + } }
--- a/engine/core/video/fonts/textrenderpool.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/fonts/textrenderpool.h Thu Oct 21 18:50:50 2010 +0000 @@ -61,6 +61,10 @@ */ ~TextRenderPool(); + /** Invalidates all cached text images + */ + void invalidateCachedText(); + /** Get a string image */ Image* getRenderedText( FontBase* fontbase, const std::string& text);
--- a/engine/core/video/image.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/image.h Thu Oct 21 18:50:50 2010 +0000 @@ -146,6 +146,10 @@ */ Image(const uint8_t* data, unsigned int width, unsigned int height); + /** Invalidates the Image causing it to be reset or re-loaded + */ + virtual void invalidate() = 0; + /** Renders itself to the Destination surface at the rectangle rect. * * @param rect The position and clipping where to draw this image to.
--- a/engine/core/video/imagepool.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/imagepool.h Thu Oct 21 18:50:50 2010 +0000 @@ -50,6 +50,16 @@ */ virtual ~ImagePool() {} + void invalidateLoadedImages() { + std::vector<PoolEntry*>::iterator it; + for (it = m_entries.begin(); it != m_entries.end(); it++) { + PoolEntry* entry = *it; + if( entry->resource) { + static_cast<Image*>(entry->resource)->invalidate(); + } + } + } + inline Image& getImage(unsigned int index) { return static_cast<Image&>(get(index)); }
--- a/engine/core/video/opengl/glimage.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/opengl/glimage.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -62,6 +62,10 @@ cleanup(); } + void GLImage::invalidate() { + resetGlimage(); + } + void GLImage::resetGlimage() { cleanup();
--- a/engine/core/video/opengl/glimage.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/opengl/glimage.h Thu Oct 21 18:50:50 2010 +0000 @@ -60,6 +60,7 @@ GLImage(SDL_Surface* surface); GLImage(const uint8_t* data, unsigned int width, unsigned int height); virtual ~GLImage(); + void invalidate(); void render(const Rect& rect, SDL_Surface* dst, unsigned char alpha = 255); void saveImage(const std::string& filename); bool putPixel(int x, int y, int r, int g, int b, int a = 255);
--- a/engine/core/video/opengl/renderbackendopengl.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/opengl/renderbackendopengl.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -76,16 +76,6 @@ } Image* RenderBackendOpenGL::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){ - m_screenMode = mode; - unsigned int width = mode.getWidth(); - unsigned int height = mode.getHeight(); - unsigned char bitsPerPixel = mode.getBPP(); - bool fs = mode.isFullScreen(); - Uint32 flags = mode.getSDLFlags(); - - delete m_screen; - m_screen = 0; - if(icon != "") { SDL_Surface *img = IMG_Load(icon.c_str()); if(img != NULL) { @@ -93,31 +83,32 @@ } } + Image *image = setScreenMode(mode); + + SDL_WM_SetCaption(title.c_str(), 0); + + return image; + } + + Image* RenderBackendOpenGL::setScreenMode(const ScreenMode& mode) { + uint16_t width = mode.getWidth(); + uint16_t height = mode.getHeight(); + uint16_t bitsPerPixel = mode.getBPP(); + bool fs = mode.isFullScreen(); + uint32_t flags = mode.getSDLFlags(); + SDL_Surface* screen = NULL; - if( 0 == bitsPerPixel ) { - /// autodetect best mode - unsigned char possibleBitsPerPixel[] = {32, 24, 16, 0}; - int i = 0; - while( true ) { - bitsPerPixel = possibleBitsPerPixel[i]; - if( !bitsPerPixel ) { - throw SDLException("Videomode not available"); - } + if (bitsPerPixel != 0) { + uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags); + if (!bpp){ + throw SDLException("Selected video mode not supported!"); + } + } - if ( SDL_VideoModeOK(width, height, bitsPerPixel, flags) ) { - screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); - if( screen ) { - break; - } - } - ++i; - } - } else { - if ( !SDL_VideoModeOK(width, height, bitsPerPixel, flags) ) { - throw SDLException("Videomode not available"); - } - screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); + screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); + if( !screen ) { + throw SDLException("Unable to set video mode selected!"); } FL_LOG(_log, LMsg("RenderBackendOpenGL") @@ -125,13 +116,11 @@ << " at " << int(bitsPerPixel) << " bpp"); //update the screen mode with the actual flags used - - m_screenMode = ScreenMode(m_screenMode.getWidth(), - m_screenMode.getHeight(), - m_screenMode.getBPP(), + m_screenMode = ScreenMode(width, + height, + bitsPerPixel, screen->flags); - SDL_WM_SetCaption(title.c_str(), 0); if (!screen) { throw SDLException(SDL_GetError()); @@ -152,10 +141,12 @@ glPointSize(1.0); glLineWidth(1.0); + delete m_screen; m_screen = new GLImage(screen); return m_screen; } + void RenderBackendOpenGL::startFrame() { if(m_clear) { clearBackBuffer();
--- a/engine/core/video/opengl/renderbackendopengl.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/opengl/renderbackendopengl.h Thu Oct 21 18:50:50 2010 +0000 @@ -50,6 +50,7 @@ void clearBackBuffer(); Image* createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon); + Image* setScreenMode(const ScreenMode& mode); Image* createImage(const uint8_t* data, unsigned int width, unsigned int height); Image* createImage(SDL_Surface* surface); bool putPixel(int x, int y, int r, int g, int b, int a = 255);
--- a/engine/core/video/renderbackend.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/renderbackend.h Thu Oct 21 18:50:50 2010 +0000 @@ -92,6 +92,12 @@ */ virtual Image* createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon) = 0; + /** Sets the mainscreen display mode. + * @param mode The ScreenMode to change the display to. @see FIFE::ScreenMode. + * @return The new Screen Image + */ + virtual Image* setScreenMode(const ScreenMode& mode) = 0; + /** Creates an Image suitable for this renderbackend. * @param data Pointer to the imagedata (needs to be in RGBA, 8 bits per channel). * @param width Width of the image. @@ -118,7 +124,8 @@ SDL_Surface* getSurface(); - /** Get current video mode + /** Get current screen mode + * @return The current screen mode */ const ScreenMode& getCurrentScreenMode() const;
--- a/engine/core/video/sdl/renderbackendsdl.cpp Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/sdl/renderbackendsdl.cpp Thu Oct 21 18:50:50 2010 +0000 @@ -80,13 +80,6 @@ } Image* RenderBackendSDL::createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon){ - m_screenMode = mode; - unsigned int width = mode.getWidth(); - unsigned int height = mode.getHeight(); - unsigned char bitsPerPixel = mode.getBPP(); - bool fs = mode.isFullScreen(); - Uint32 flags = mode.getSDLFlags(); - if(icon != "") { SDL_Surface *img = IMG_Load(icon.c_str()); if(img != NULL) { @@ -94,55 +87,49 @@ } } + Image *image = setScreenMode(mode); + + SDL_WM_SetCaption(title.c_str(), 0); + + return image; + } + + Image* RenderBackendSDL::setScreenMode(const ScreenMode& mode) { + uint16_t width = mode.getWidth(); + uint16_t height = mode.getHeight(); + uint16_t bitsPerPixel = mode.getBPP(); + bool fs = mode.isFullScreen(); + uint32_t flags = mode.getSDLFlags(); + SDL_Surface* screen = NULL; - if( 0 == bitsPerPixel ) { - /// autodetect best mode - unsigned char possibleBitsPerPixel[] = {16, 24, 32, 0}; - int i = 0; - while( true ) { - bitsPerPixel = possibleBitsPerPixel[i]; - if( !bitsPerPixel ) { - // Last try, sometimes VideoModeOK seems to lie. - // Try bpp=0 - screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); - if( !screen ) { - throw SDLException("Videomode not available"); - } - break; - } - bitsPerPixel = SDL_VideoModeOK(width, height, bitsPerPixel, flags); - if ( bitsPerPixel ) { - screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); - if( screen ) { - break; - } - } - ++i; + if (bitsPerPixel != 0) { + uint16_t bpp = SDL_VideoModeOK(width, height, bitsPerPixel, flags); + if (!bpp){ + throw SDLException("Selected video mode not supported!"); } - } else { - if ( !SDL_VideoModeOK(width, height, bitsPerPixel, flags) ) { - throw SDLException("Videomode not available"); - } - screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); } + + screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags); + if( !screen ) { + throw SDLException("Unable to set video mode selected!"); + } + FL_LOG(_log, LMsg("RenderBackendSDL") << "Videomode " << width << "x" << height << " at " << int(screen->format->BitsPerPixel) << " bpp"); //update the screen mode with the actual flags used - - m_screenMode = ScreenMode(m_screenMode.getWidth(), - m_screenMode.getHeight(), - m_screenMode.getBPP(), + m_screenMode = ScreenMode(width, + height, + bitsPerPixel, screen->flags); - SDL_WM_SetCaption(title.c_str(), NULL); - if (!screen) { throw SDLException(SDL_GetError()); } + delete m_screen; m_screen = new SDLImage(screen); return m_screen; }
--- a/engine/core/video/sdl/renderbackendsdl.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/sdl/renderbackendsdl.h Thu Oct 21 18:50:50 2010 +0000 @@ -52,6 +52,7 @@ void clearBackBuffer(); Image* createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon); + Image* setScreenMode(const ScreenMode& mode); Image* createImage(const uint8_t* data, unsigned int width, unsigned int height); Image* createImage(SDL_Surface* surface); bool putPixel(int x, int y, int r, int g, int b, int a = 255);
--- a/engine/core/video/sdl/sdlimage.h Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/sdl/sdlimage.h Thu Oct 21 18:50:50 2010 +0000 @@ -42,6 +42,7 @@ SDLImage(SDL_Surface* surface); SDLImage(const uint8_t* data, unsigned int width, unsigned int height); virtual ~SDLImage(); + void invalidate() {}; //do nothing for SDL images (for now) void render(const Rect& rect, SDL_Surface* dst, unsigned char alpha = 255); void saveImage(const std::string& filename); bool putPixel(int x, int y, int r, int g, int b, int a = 255);
--- a/engine/core/video/video.i Fri Oct 15 18:54:34 2010 +0000 +++ b/engine/core/video/video.i Thu Oct 21 18:50:50 2010 +0000 @@ -155,6 +155,7 @@ public: virtual ~RenderBackend(); virtual const std::string& getName() const = 0; + Image* getScreenImage() const { return m_screen; }; void captureScreen(const std::string& filename); SDL_Surface* getSurface(); @@ -258,6 +259,7 @@ void fillDeviceCaps(); std::vector<ScreenMode> getSupportedScreenModes() const; + ScreenMode getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs) const; std::string getDriverName() const; std::vector<string> getAvailableDrivers() const; bool isHwSurfaceAvail() const;