diff --git a/client/CMT.h b/client/CMT.h index abd6596f5..e73c065b2 100644 --- a/client/CMT.h +++ b/client/CMT.h @@ -9,17 +9,9 @@ */ #pragma once -struct SDL_Texture; struct SDL_Renderer; -struct SDL_Surface; - -extern SDL_Texture * screenTexture; extern SDL_Renderer * mainRenderer; -extern SDL_Surface *screen; // main screen surface -extern SDL_Surface *screen2; // and hlp surface (used to store not-active interfaces layer) -extern SDL_Surface *screenBuf; // points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed - /// Notify user about encountered fatal error and terminate the game /// Defined in clientapp EntryPoint /// TODO: decide on better location for this method diff --git a/client/adventureMap/AdventureMapInterface.cpp b/client/adventureMap/AdventureMapInterface.cpp index b77809af7..e7a2a0619 100644 --- a/client/adventureMap/AdventureMapInterface.cpp +++ b/client/adventureMap/AdventureMapInterface.cpp @@ -34,7 +34,6 @@ #include "../render/IImage.h" #include "../render/IRenderHandler.h" #include "../render/IScreenHandler.h" -#include "../CMT.h" #include "../PlayerLocalState.h" #include "../CPlayerInterface.h" @@ -131,8 +130,6 @@ void AdventureMapInterface::activate() adjustActiveness(); - screenBuf = screen; - if(LOCPLINT) { LOCPLINT->cingconsole->activate(); @@ -453,8 +450,7 @@ void AdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID) widget->getInfoBar()->showDate(); onHeroChanged(nullptr); - Canvas canvas = Canvas::createFromSurface(screen, CanvasScalingPolicy::AUTO); - showAll(canvas); + GH.windows().totalRedraw(); mapAudio->onPlayerTurnStarted(); if(settings["session"]["autoSkip"].Bool() && !GH.isKeyboardShiftDown()) diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 6608ca44d..35cef9316 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -20,13 +20,13 @@ #include "../CGameInfo.h" #include "../adventureMap/AdventureMapInterface.h" +#include "../render/Canvas.h" #include "../render/Colors.h" #include "../render/Graphics.h" #include "../render/IFont.h" #include "../render/EFont.h" #include "../renderSDL/ScreenHandler.h" #include "../renderSDL/RenderHandler.h" -#include "../CMT.h" #include "../CPlayerInterface.h" #include "../battle/BattleInterface.h" @@ -104,21 +104,13 @@ void CGuiHandler::renderFrame() if (settings["video"]["showfps"].Bool()) drawFPSCounter(); - SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch); - } - - SDL_RenderClear(mainRenderer); - SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr); - - { - boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); - - CCS->curh->render(); + screenHandlerInstance->updateScreenTexture(); windows().onFrameRendered(); + CCS->curh->update(); } - SDL_RenderPresent(mainRenderer); + screenHandlerInstance->presentScreenTexture(); framerate().framerateDelay(); // holds a constant FPS } @@ -181,19 +173,12 @@ Point CGuiHandler::screenDimensions() const void CGuiHandler::drawFPSCounter() { - int scaling = screenHandlerInstance->getScalingFactor(); - int x = 7 * scaling; - int y = screen->h-20 * scaling; - int width3digitFPSIncludingPadding = 48 * scaling; - int heightFPSTextIncludingPadding = 11 * scaling; - SDL_Rect overlay = { x, y, width3digitFPSIncludingPadding, heightFPSTextIncludingPadding}; - uint32_t black = SDL_MapRGB(screen->format, 10, 10, 10); - SDL_FillRect(screen, &overlay, black); - + Canvas target = GH.screenHandler().getScreenCanvas(); + Rect targetArea(0, screenDimensions().y - 20, 48, 11); std::string fps = std::to_string(framerate().getFramerate())+" FPS"; - const auto & font = GH.renderHandler().loadFont(FONT_SMALL); - font->renderTextLeft(screen, fps, Colors::WHITE, Point(8 * scaling, screen->h-22 * scaling)); + target.drawColor(targetArea, ColorRGBA(10, 10, 10)); + target.drawText(targetArea.center(), EFonts::FONT_SMALL, Colors::WHITE, ETextAlignment::CENTER, fps); } bool CGuiHandler::amIGuiThread() diff --git a/client/gui/CIntObject.cpp b/client/gui/CIntObject.cpp index d38238ce6..5593d8aa3 100644 --- a/client/gui/CIntObject.cpp +++ b/client/gui/CIntObject.cpp @@ -15,8 +15,8 @@ #include "EventDispatcher.h" #include "Shortcut.h" #include "../render/Canvas.h" +#include "../render/IScreenHandler.h" #include "../windows/CMessage.h" -#include "../CMT.h" CIntObject::CIntObject(int used_, Point pos_): parent_m(nullptr), @@ -238,15 +238,8 @@ void CIntObject::redraw() } else { - Canvas buffer = Canvas::createFromSurface(screenBuf, CanvasScalingPolicy::AUTO); - + Canvas buffer = GH.screenHandler().getScreenCanvas(); showAll(buffer); - if(screenBuf != screen) - { - Canvas screenBuffer = Canvas::createFromSurface(screen, CanvasScalingPolicy::AUTO); - - showAll(screenBuffer); - } } } } diff --git a/client/gui/CursorHandler.cpp b/client/gui/CursorHandler.cpp index fbc5922f8..2235962f9 100644 --- a/client/gui/CursorHandler.cpp +++ b/client/gui/CursorHandler.cpp @@ -260,6 +260,11 @@ void CursorHandler::updateSpellcastCursor() } void CursorHandler::render() +{ + cursor->render(); +} + +void CursorHandler::update() { if(!showing) return; @@ -267,7 +272,7 @@ void CursorHandler::render() if (type == Cursor::Type::SPELLBOOK) updateSpellcastCursor(); - cursor->render(); + cursor->update(); } void CursorHandler::hide() diff --git a/client/gui/CursorHandler.h b/client/gui/CursorHandler.h index acaccaaa8..63a19f518 100644 --- a/client/gui/CursorHandler.h +++ b/client/gui/CursorHandler.h @@ -179,6 +179,7 @@ public: Point getPivotOffsetCombat(size_t index); void render(); + void update(); void hide(); void show(); diff --git a/client/gui/WindowHandler.cpp b/client/gui/WindowHandler.cpp index 6c5940c30..612160055 100644 --- a/client/gui/WindowHandler.cpp +++ b/client/gui/WindowHandler.cpp @@ -14,11 +14,10 @@ #include "CIntObject.h" #include "CursorHandler.h" -#include "../CMT.h" #include "../CGameInfo.h" #include "../render/Canvas.h" +#include "../render/IScreenHandler.h" #include "../render/Colors.h" -#include "../renderSDL/SDL_Extensions.h" void WindowHandler::popWindow(std::shared_ptr top) { @@ -42,9 +41,6 @@ void WindowHandler::pushWindow(std::shared_ptr newInt) if (vstd::contains(windowsStack, newInt)) throw std::runtime_error("Attempt to add already existing window to stack!"); - //a new interface will be present, we'll need to use buffer surface (unless it's advmapint that will alter screenBuf on activate anyway) - screenBuf = screen2; - if(!windowsStack.empty()) windowsStack.back()->deactivate(); windowsStack.push_back(newInt); @@ -111,11 +107,10 @@ void WindowHandler::totalRedrawImpl() { logGlobal->debug("totalRedraw requested!"); - Canvas target = Canvas::createFromSurface(screen2, CanvasScalingPolicy::AUTO); + Canvas target = GH.screenHandler().getScreenCanvas(); for(auto & elem : windowsStack) elem->showAll(target); - CSDL_Ext::blitAt(screen2, 0, 0, screen); } void WindowHandler::simpleRedraw() @@ -130,11 +125,7 @@ void WindowHandler::simpleRedraw() void WindowHandler::simpleRedrawImpl() { - //update only top interface and draw background - if(windowsStack.size() > 1) - CSDL_Ext::blitAt(screen2, 0, 0, screen); //blit background - - Canvas target = Canvas::createFromSurface(screen, CanvasScalingPolicy::AUTO); + Canvas target = GH.screenHandler().getScreenCanvas(); if(!windowsStack.empty()) windowsStack.back()->show(target); //blit active interface/window diff --git a/client/render/ICursor.h b/client/render/ICursor.h index af9e2f1c6..6e0fa4f19 100644 --- a/client/render/ICursor.h +++ b/client/render/ICursor.h @@ -23,6 +23,7 @@ public: virtual void setImage(std::shared_ptr image, const Point & pivotOffset) = 0; virtual void setCursorPosition( const Point & newPos ) = 0; virtual void render() = 0; + virtual void update() = 0; virtual void setVisible( bool on) = 0; }; diff --git a/client/render/IScreenHandler.h b/client/render/IScreenHandler.h index f3b6d5eee..84a75a09b 100644 --- a/client/render/IScreenHandler.h +++ b/client/render/IScreenHandler.h @@ -15,6 +15,8 @@ class Point; class Rect; VCMI_LIB_NAMESPACE_END +class Canvas; + class IScreenHandler { public: @@ -29,6 +31,15 @@ public: /// Fills screen with black color, erasing any existing content virtual void clearScreen() = 0; + /// Returns canvas that can be used to display objects on screen + virtual Canvas getScreenCanvas() const = 0; + + /// Synchronizes internal screen texture. Screen canvas may not be modified during this call + virtual void updateScreenTexture() = 0; + + /// Presents screen texture on the screen + virtual void presentScreenTexture() = 0; + /// Returns list of resolutions supported by current screen virtual std::vector getSupportedResolutions() const = 0; diff --git a/client/renderSDL/CursorHardware.cpp b/client/renderSDL/CursorHardware.cpp index 569ce7399..96f9bc09a 100644 --- a/client/renderSDL/CursorHardware.cpp +++ b/client/renderSDL/CursorHardware.cpp @@ -92,3 +92,8 @@ void CursorHardware::render() { //no-op } + +void CursorHardware::update() +{ + //no-op +} diff --git a/client/renderSDL/CursorHardware.h b/client/renderSDL/CursorHardware.h index 02b75fca5..907fb40e2 100644 --- a/client/renderSDL/CursorHardware.h +++ b/client/renderSDL/CursorHardware.h @@ -30,6 +30,7 @@ public: void setImage(std::shared_ptr image, const Point & pivotOffset) override; void setCursorPosition( const Point & newPos ) override; void render() override; + void update() override; void setVisible( bool on) override; }; diff --git a/client/renderSDL/CursorSoftware.cpp b/client/renderSDL/CursorSoftware.cpp index 1e84ecd06..4fe791b70 100644 --- a/client/renderSDL/CursorSoftware.cpp +++ b/client/renderSDL/CursorSoftware.cpp @@ -21,12 +21,15 @@ #include #include -void CursorSoftware::render() +void CursorSoftware::update() { //texture must be updated in the main (renderer) thread, but changes to cursor type may come from other threads if (needUpdate) updateTexture(); +} +void CursorSoftware::render() +{ Point renderPos = pos - pivot; SDL_Rect destRect; diff --git a/client/renderSDL/CursorSoftware.h b/client/renderSDL/CursorSoftware.h index cb43bb1e5..5462f9701 100644 --- a/client/renderSDL/CursorSoftware.h +++ b/client/renderSDL/CursorSoftware.h @@ -38,6 +38,7 @@ public: void setImage(std::shared_ptr image, const Point & pivotOffset) override; void setCursorPosition( const Point & newPos ) override; void render() override; + void update() override; void setVisible( bool on) override; }; diff --git a/client/renderSDL/SDLImage.cpp b/client/renderSDL/SDLImage.cpp index d584f4683..562a4fa2a 100644 --- a/client/renderSDL/SDLImage.cpp +++ b/client/renderSDL/SDLImage.cpp @@ -324,10 +324,21 @@ void SDLImageShared::exportBitmap(const boost::filesystem::path& path, SDL_Palet bool SDLImageShared::isTransparent(const Point & coords) const { assert(upscalingInProgress == false); - if (surf) - return CSDL_Ext::isTransparent(surf, coords.x - margins.x, coords.y - margins.y); - else + if (!surf) return true; + + Point test = coords - margins; + + if (test.x < 0 || test.y < 0 || test.x >= surf->w || test.y >= surf->h) + return true; + + SDL_Color color; + SDL_GetRGBA(CSDL_Ext::getPixel(surf, test.x, test.y), surf->format, &color.r, &color.g, &color.b, &color.a); + + bool pixelTransparent = color.a < 128; + bool pixelCyan = (color.r == 0 && color.g == 255 && color.b == 255); + + return pixelTransparent || pixelCyan; } Rect SDLImageShared::contentRect() const diff --git a/client/renderSDL/SDLImageScaler.cpp b/client/renderSDL/SDLImageScaler.cpp index d2a958f5f..af41992f0 100644 --- a/client/renderSDL/SDLImageScaler.cpp +++ b/client/renderSDL/SDLImageScaler.cpp @@ -12,7 +12,6 @@ #include "SDL_Extensions.h" -#include "../CMT.h" #include "../xBRZ/xbrz.h" #include @@ -211,7 +210,7 @@ SDLImageScaler::SDLImageScaler(SDL_Surface * surf, const Rect & virtualDimension if (optimizeImage) { SDLImageOptimizer optimizer(surf, virtualDimensions); - optimizer.optimizeSurface(screen); + optimizer.optimizeSurface(nullptr); intermediate = optimizer.acquireResultSurface(); virtualDimensionsInput = optimizer.getResultDimensions(); } diff --git a/client/renderSDL/SDL_Extensions.cpp b/client/renderSDL/SDL_Extensions.cpp index 38818999f..806ad8bb1 100644 --- a/client/renderSDL/SDL_Extensions.cpp +++ b/client/renderSDL/SDL_Extensions.cpp @@ -59,36 +59,31 @@ SDL_Color CSDL_Ext::toSDL(const ColorRGBA & color) return result; } -void CSDL_Ext::setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors) -{ - SDL_SetPaletteColors(surface->format->palette,colors,firstcolor,ncolors); -} - -void CSDL_Ext::setAlpha(SDL_Surface * bg, int value) -{ - SDL_SetSurfaceAlphaMod(bg, value); -} - SDL_Surface * CSDL_Ext::newSurface(const Point & dimensions) { - return newSurface(dimensions, screen); + return newSurface(dimensions, nullptr); } SDL_Surface * CSDL_Ext::newSurface(const Point & dimensions, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given { - SDL_Surface * ret = SDL_CreateRGBSurface(0,dimensions.x,dimensions.y,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); + SDL_Surface * ret = nullptr; + + if (mod != nullptr) + ret = SDL_CreateRGBSurface(0,dimensions.x,dimensions.y,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask); + else + ret = SDL_CreateRGBSurfaceWithFormat(0,dimensions.x,dimensions.y,32,SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB8888); if(ret == nullptr) { const char * error = SDL_GetError(); - std::string messagePattern = "Failed to create SDL Surface of size %d x %d, %d bpp. Reason: %s"; - std::string message = boost::str(boost::format(messagePattern) % dimensions.x % dimensions.y % mod->format->BitsPerPixel % error); + std::string messagePattern = "Failed to create SDL Surface of size %d x %d. Reason: %s"; + std::string message = boost::str(boost::format(messagePattern) % dimensions.x % dimensions.y % error); handleFatalError(message, true); } - if (mod->format->palette) + if (mod && mod->format->palette) { assert(ret->format->palette); assert(ret->format->palette->ncolors >= mod->format->palette->ncolors); @@ -97,25 +92,6 @@ SDL_Surface * CSDL_Ext::newSurface(const Point & dimensions, SDL_Surface * mod) return ret; } -SDL_Surface * CSDL_Ext::copySurface(SDL_Surface * mod) //returns copy of given surface -{ - //return SDL_DisplayFormat(mod); - return SDL_ConvertSurface(mod, mod->format, mod->flags); -} - -template -SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height) -{ - uint32_t rMask = 0, gMask = 0, bMask = 0, aMask = 0; - - Channels::px::r.set((uint8_t*)&rMask, 255); - Channels::px::g.set((uint8_t*)&gMask, 255); - Channels::px::b.set((uint8_t*)&bMask, 255); - Channels::px::a.set((uint8_t*)&aMask, 255); - - return SDL_CreateRGBSurface(0, width, height, bpp * 8, rMask, gMask, bMask, aMask); -} - void CSDL_Ext::blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst) { CSDL_Ext::blitSurface(src, dst, Point(x, y)); @@ -537,54 +513,23 @@ void CSDL_Ext::drawBorder( SDL_Surface * sur, const Rect &r, const SDL_Color &co drawBorder(sur, r.x, r.y, r.w, r.h, color, depth); } -CSDL_Ext::TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest) -{ - switch(dest->format->BytesPerPixel) - { - case 3: - return ColorPutter<3>::PutColor; - case 4: - return ColorPutter<4>::PutColor; - default: - logGlobal->error("%d bpp is not supported!", (int)dest->format->BitsPerPixel); - return nullptr; - } -} - uint8_t * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int x, const int y) { return (uint8_t *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel; } -bool CSDL_Ext::isTransparent( SDL_Surface * srf, const Point & position ) -{ - return isTransparent(srf, position.x, position.y); -} - -bool CSDL_Ext::isTransparent( SDL_Surface * srf, int x, int y ) -{ - if (x < 0 || y < 0 || x >= srf->w || y >= srf->h) - return true; - - SDL_Color color; - - SDL_GetRGBA(CSDL_Ext::getPixel(srf, x, y), srf->format, &color.r, &color.g, &color.b, &color.a); - - bool pixelTransparent = color.a < 128; - bool pixelCyan = (color.r == 0 && color.g == 255 && color.b == 255); - - return pixelTransparent || pixelCyan; -} - void CSDL_Ext::putPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const uint8_t & R, const uint8_t & G, const uint8_t & B, uint8_t A) { uint8_t *p = getPxPtr(ekran, x, y); - getPutterFor(ekran)(p, R, G, B); switch(ekran->format->BytesPerPixel) { - case 3: Channels::px<3>::a.set(p, A); break; - case 4: Channels::px<4>::a.set(p, A); break; + case 3: + ColorPutter<3>::PutColor(p, R, G, B); + Channels::px<3>::a.set(p, A); break; + case 4: + ColorPutter<4>::PutColor(p, R, G, B); + Channels::px<4>::a.set(p, A); break; } } @@ -719,6 +664,3 @@ void CSDL_Ext::getClipRect(SDL_Surface * src, Rect & other) other = CSDL_Ext::fromSDL(rect); } - -template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<3>(int, int); -template SDL_Surface * CSDL_Ext::createSurfaceWithBpp<4>(int, int); diff --git a/client/renderSDL/SDL_Extensions.h b/client/renderSDL/SDL_Extensions.h index 6d01d2520..f7d12f310 100644 --- a/client/renderSDL/SDL_Extensions.h +++ b/client/renderSDL/SDL_Extensions.h @@ -13,20 +13,9 @@ #include "../../lib/Color.h" struct SDL_Rect; -struct SDL_Window; -struct SDL_Renderer; -struct SDL_Texture; struct SDL_Surface; struct SDL_Color; -VCMI_LIB_NAMESPACE_BEGIN - -class PlayerColor; -class Rect; -class Point; - -VCMI_LIB_NAMESPACE_END - namespace CSDL_Ext { @@ -42,12 +31,6 @@ ColorRGBA fromSDL(const SDL_Color & color); /// creates SDL_Color using provided Color SDL_Color toSDL(const ColorRGBA & color); -void setColors(SDL_Surface *surface, SDL_Color *colors, int firstcolor, int ncolors); -void setAlpha(SDL_Surface * bg, int value); - -using TColorPutter = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, const uint8_t &); -using TColorPutterAlpha = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, const uint8_t &, const uint8_t &); - void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst); void blitAt(SDL_Surface * src, const Rect & pos, SDL_Surface * dst); @@ -67,11 +50,8 @@ using TColorPutterAlpha = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, SDL_Surface * verticalFlip(SDL_Surface * toRot); //vertical flip SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip uint32_t getPixel(SDL_Surface * surface, const int & x, const int & y, bool colorByte = false); - bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position - bool isTransparent(SDL_Surface * srf, const Point & position); //checks if surface is transparent at given position uint8_t * getPxPtr(const SDL_Surface * const & srf, const int x, const int y); - TColorPutter getPutterFor(SDL_Surface * const & dest); template int blit8bppAlphaTo24bppT(const SDL_Surface * src, const Rect & srcRect, SDL_Surface * dst, const Point & dstPoint, uint8_t alpha); //blits 8 bpp surface with alpha channel to 24 bpp surface @@ -86,9 +66,6 @@ using TColorPutterAlpha = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, SDL_Surface * newSurface(const Point & dimensions, SDL_Surface * mod); //creates new surface, with flags/format same as in surface given SDL_Surface * newSurface(const Point & dimensions); //creates new surface, with flags/format same as in screen surface - SDL_Surface * copySurface(SDL_Surface * mod); //returns copy of given surface - template - SDL_Surface * createSurfaceWithBpp(int width, int height); //create surface with give bits per pixels value template void convertToGrayscaleBpp(SDL_Surface * surf, const Rect & rect); @@ -100,25 +77,4 @@ using TColorPutterAlpha = void (*)(uint8_t *&, const uint8_t &, const uint8_t &, void setDefaultColorKey(SDL_Surface * surface); ///set key-color to 0,255,255 only if it exactly mapped void setDefaultColorKeyPresize(SDL_Surface * surface); - - /// helper that will safely set and un-set ClipRect for SDL_Surface - class CClipRectGuard: boost::noncopyable - { - SDL_Surface * surf; - Rect oldRect; - - int getScalingFactor() const; - - public: - CClipRectGuard(SDL_Surface * surface, const Rect & rect): surf(surface) - { - CSDL_Ext::getClipRect(surf, oldRect); - CSDL_Ext::setClipRect(surf, rect * getScalingFactor()); - } - - ~CClipRectGuard() - { - CSDL_Ext::setClipRect(surf, oldRect); - } - }; } diff --git a/client/renderSDL/ScreenHandler.cpp b/client/renderSDL/ScreenHandler.cpp index 93864b9d2..193bf928d 100644 --- a/client/renderSDL/ScreenHandler.cpp +++ b/client/renderSDL/ScreenHandler.cpp @@ -11,11 +11,13 @@ #include "StdInc.h" #include "ScreenHandler.h" +#include "../CGameInfo.h" +#include "../CMT.h" #include "../eventsSDL/NotificationHandler.h" #include "../gui/CGuiHandler.h" +#include "../gui/CursorHandler.h" #include "../gui/WindowHandler.h" -#include "../renderSDL/SDL_Extensions.h" -#include "CMT.h" +#include "../render/Canvas.h" #include "../../lib/CConfigHandler.h" #include "../../lib/constants/StringConstants.h" @@ -31,12 +33,7 @@ #include // TODO: should be made into a private members of ScreenHandler -static SDL_Window * mainWindow = nullptr; SDL_Renderer * mainRenderer = nullptr; -SDL_Texture * screenTexture = nullptr; -SDL_Surface * screen = nullptr; //main screen surface -SDL_Surface * screen2 = nullptr; //and hlp surface (used to store not-active interfaces layer) -SDL_Surface * screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed static const std::string NAME = GameConstants::VCMI_VERSION; //application name static constexpr Point heroes3Resolution = Point(800, 600); @@ -434,18 +431,6 @@ void ScreenHandler::initializeScreenBuffers() throw std::runtime_error("Unable to create screen texture"); } - screen2 = CSDL_Ext::copySurface(screen); - - if(nullptr == screen2) - { - throw std::runtime_error("Unable to copy surface\n"); - } - - if (GH.windows().count() > 1) - screenBuf = screen2; - else - screenBuf = screen; - clearScreen(); } @@ -590,15 +575,6 @@ int ScreenHandler::getPreferredRenderingDriver() const void ScreenHandler::destroyScreenBuffers() { - // screenBuf is not a separate surface, but points to either screen or screen2 - just set to null - screenBuf = nullptr; - - if(nullptr != screen2) - { - SDL_FreeSurface(screen2); - screen2 = nullptr; - } - if(nullptr != screen) { SDL_FreeSurface(screen); @@ -644,6 +620,24 @@ void ScreenHandler::clearScreen() SDL_RenderPresent(mainRenderer); } +Canvas ScreenHandler::getScreenCanvas() const +{ + return Canvas::createFromSurface(screen, CanvasScalingPolicy::AUTO); +} + +void ScreenHandler::updateScreenTexture() +{ + SDL_UpdateTexture(screenTexture, nullptr, screen->pixels, screen->pitch); +} + +void ScreenHandler::presentScreenTexture() +{ + SDL_RenderClear(mainRenderer); + SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr); + CCS->curh->render(); + SDL_RenderPresent(mainRenderer); +} + std::vector ScreenHandler::getSupportedResolutions() const { int displayID = getPreferredDisplayIndex(); diff --git a/client/renderSDL/ScreenHandler.h b/client/renderSDL/ScreenHandler.h index 6a9026d7b..2e6282406 100644 --- a/client/renderSDL/ScreenHandler.h +++ b/client/renderSDL/ScreenHandler.h @@ -10,14 +10,14 @@ #pragma once +#include "../../lib/Point.h" +#include "../render/IScreenHandler.h" + struct SDL_Texture; struct SDL_Window; struct SDL_Renderer; struct SDL_Surface; -#include "../../lib/Point.h" -#include "../render/IScreenHandler.h" - enum class EWindowMode { // game runs in a window that covers part of the screen @@ -44,6 +44,10 @@ enum class EUpscalingFilter /// This class is responsible for management of game window and its main rendering surface class ScreenHandler final : public IScreenHandler { + SDL_Window * mainWindow = nullptr; + SDL_Texture * screenTexture = nullptr; + SDL_Surface * screen = nullptr; + EUpscalingFilter upscalingFilter = EUpscalingFilter::AUTO; /// Dimensions of target surfaces/textures, this value is what game logic views as screen size @@ -114,6 +118,10 @@ public: int getInterfaceScalingPercentage() const final; + Canvas getScreenCanvas() const final; + void updateScreenTexture() final; + void presentScreenTexture() final; + std::vector getSupportedResolutions() const final; std::vector getSupportedResolutions(int displayIndex) const; std::tuple getSupportedScalingRange() const final;