From aca33e55872a147a5b4707b178e685b81a9b86f0 Mon Sep 17 00:00:00 2001 From: Misa Date: Fri, 5 Mar 2021 20:12:01 -0800 Subject: [PATCH 1/2] De-duplicate surface recreation in GraphicsUtil Here I'm using "surface recreation" to mean allocating a new surface with almost the exact same properties as a given previous. As you can see, GraphicsUtil likes to recreate surfaces all the time - copying the masks and flags (unused lol) of an existing surface - and only varies it by the dimensions of the new surface. As you can see, this is a lot less wordy and a lot less repetitive than copy-pasting it a bunch. --- desktop_version/src/GraphicsUtil.cpp | 87 +++++++++++++++++----------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/desktop_version/src/GraphicsUtil.cpp b/desktop_version/src/GraphicsUtil.cpp index d8d13f59..ca7ff512 100644 --- a/desktop_version/src/GraphicsUtil.cpp +++ b/desktop_version/src/GraphicsUtil.cpp @@ -11,6 +11,51 @@ void setRect( SDL_Rect& _r, int x, int y, int w, int h ) _r.h = h; } +static SDL_Surface* RecreateSurfaceWithDimensions( + SDL_Surface* surface, + const int width, + const int height +) { + SDL_Surface* retval; + + if (surface == NULL) + { + return NULL; + } + + retval = SDL_CreateRGBSurface( + surface->flags, + width, + height, + surface->format->BitsPerPixel, + surface->format->Rmask, + surface->format->Gmask, + surface->format->Bmask, + surface->format->Amask + ); + + if (retval == NULL) + { + return NULL; + } + + return retval; +} + +static SDL_Surface* RecreateSurface(SDL_Surface* surface) +{ + if (surface == NULL) + { + return NULL; + } + + return RecreateSurfaceWithDimensions( + surface, + surface->w, + surface->h + ); +} + SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height ) { // Create an SDL_Rect with the area of the _surface @@ -21,15 +66,10 @@ SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, i area.h = height; //Convert to the correct display format after nabbing the new _surface or we will slow things down. - SDL_Surface* preSurface = SDL_CreateRGBSurface( - SDL_SWSURFACE, + SDL_Surface* preSurface = RecreateSurfaceWithDimensions( + metaSurface, width, - height, - metaSurface->format->BitsPerPixel, - metaSurface->format->Rmask, - metaSurface->format->Gmask, - metaSurface->format->Bmask, - metaSurface->format->Amask + height ); // Lastly, apply the area from the meta _surface onto the whole of the sub _surface. @@ -103,8 +143,7 @@ SDL_Surface * ScaleSurface( SDL_Surface *_surface, int Width, int Height, SDL_Su SDL_Surface *_ret; if(Dest == NULL) { - _ret = SDL_CreateRGBSurface(_surface->flags, Width, Height, _surface->format->BitsPerPixel, - _surface->format->Rmask, _surface->format->Gmask, _surface->format->Bmask, _surface->format->Amask); + _ret = RecreateSurfaceWithDimensions(_surface, Width, Height); if(_ret == NULL) { return NULL; @@ -132,8 +171,7 @@ SDL_Surface * ScaleSurface( SDL_Surface *_surface, int Width, int Height, SDL_Su SDL_Surface * FlipSurfaceVerticle(SDL_Surface* _src) { - SDL_Surface * ret = SDL_CreateRGBSurface(_src->flags, _src->w, _src->h, _src->format->BitsPerPixel, - _src->format->Rmask, _src->format->Gmask, _src->format->Bmask, _src->format->Amask); + SDL_Surface * ret = RecreateSurface(_src); if(ret == NULL) { return NULL; @@ -168,16 +206,7 @@ void BlitSurfaceColoured( const SDL_PixelFormat& fmt = *(_src->format); - SDL_Surface* tempsurface = SDL_CreateRGBSurface( - SDL_SWSURFACE, - _src->w, - _src->h, - fmt.BitsPerPixel, - fmt.Rmask, - fmt.Gmask, - fmt.Bmask, - fmt.Amask - ); + SDL_Surface* tempsurface = RecreateSurface(_src); for(int x = 0; x < tempsurface->w; x++) { @@ -209,16 +238,7 @@ void BlitSurfaceTinted( const SDL_PixelFormat& fmt = *(_src->format); - SDL_Surface* tempsurface = SDL_CreateRGBSurface( - SDL_SWSURFACE, - _src->w, - _src->h, - fmt.BitsPerPixel, - fmt.Rmask, - fmt.Gmask, - fmt.Bmask, - fmt.Amask - ); + SDL_Surface* tempsurface = RecreateSurface(_src); for (int x = 0; x < tempsurface->w; x++) { for (int y = 0; y < tempsurface->h; y++) { @@ -295,8 +315,7 @@ void UpdateFilter(void) SDL_Surface* ApplyFilter( SDL_Surface* _src ) { - SDL_Surface* _ret = SDL_CreateRGBSurface(_src->flags, _src->w, _src->h, _src->format->BitsPerPixel, - _src->format->Rmask, _src->format->Gmask, _src->format->Bmask, _src->format->Amask); + SDL_Surface* _ret = RecreateSurface(_src); int redOffset = rand() % 4; From d19a6cc437bfb79b9e1b33b70e20d3feaadb56be Mon Sep 17 00:00:00 2001 From: Misa Date: Fri, 5 Mar 2021 20:17:56 -0800 Subject: [PATCH 2/2] Copy blend mode to recreated surface This fixes a "root cause" bug (that's existed since 2.2 and below) where recreated surfaces wouldn't preserve the blend mode of their original surface. The surface-level (pun genuinely unintended) bug that this root bug fixes is the one where there's no background to the room name during the map menu animation in Flip Mode. This is because the room name background relies on graphics.backBuffer being filled with complete black. This is achieved by a call to ClearSurface() - however, ClearSurface() actually fills it with transparent black (this is not a regression; in 2.2 and previous, this was an "inlined" FillRect(backBuffer, 0x00000000)). This would be okay, and indeed the room name background renders fine in unflipped mode - but it suddenly breaks in Flip Mode. Why? Because backBuffer gets fed through FlipSurfaceVerticle(), and FlipSurfaceVerticle() creates a temporary surface with the same dimensions and color masks as backBuffer - it, however, does NOT create it with the same blend mode, and kind of sort of just forgets that the original was SDL_BLENDMODE_NONE; the new surface is SDL_BLENDMODE_BLEND. Thus, transparency applies on the new surface, and instead of the room name being drawn against black, it gets drawn against transparency. --- desktop_version/src/GraphicsUtil.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/desktop_version/src/GraphicsUtil.cpp b/desktop_version/src/GraphicsUtil.cpp index ca7ff512..2eef6cfe 100644 --- a/desktop_version/src/GraphicsUtil.cpp +++ b/desktop_version/src/GraphicsUtil.cpp @@ -17,6 +17,7 @@ static SDL_Surface* RecreateSurfaceWithDimensions( const int height ) { SDL_Surface* retval; + SDL_BlendMode blend_mode; if (surface == NULL) { @@ -39,6 +40,9 @@ static SDL_Surface* RecreateSurfaceWithDimensions( return NULL; } + SDL_GetSurfaceBlendMode(surface, &blend_mode); + SDL_SetSurfaceBlendMode(retval, blend_mode); + return retval; }