From dd5bc398169028c8b0fbc1d1d0084fbac417b256 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 13 Oct 2019 12:50:16 +0100 Subject: [PATCH] Get a fresh window surface before rendering to it (#358) * Get a fresh window surface before rendering to it It is possible that a window surface gets invalidated since we initially obtained it. We need to call GetWindowSurface every time we want one, instead of keeping a pointer to a possibly stale one. See https://hg.libsdl.org/SDL/file/369b01006eb2/src/video/SDL_video.c#l2312 Fixes #351 --- CMakeLists.txt | 1 + SourceX/dx.cpp | 19 ++++++++----------- SourceX/miniwin/ddraw.cpp | 17 +++++++++++++++++ SourceX/miniwin/ddraw.h | 7 ++++++- SourceX/storm/storm.cpp | 4 ++-- 5 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 SourceX/miniwin/ddraw.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f55278d79..fa9f7412a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,7 @@ add_library(devilution STATIC set(devilutionx_SRCS SourceX/dx.cpp + SourceX/miniwin/ddraw.cpp SourceX/miniwin/misc.cpp SourceX/miniwin/misc_io.cpp SourceX/miniwin/misc_msg.cpp diff --git a/SourceX/dx.cpp b/SourceX/dx.cpp index b35975de0..0f8c935ff 100644 --- a/SourceX/dx.cpp +++ b/SourceX/dx.cpp @@ -22,8 +22,8 @@ SDL_Texture *texture; SDL_Palette *palette; unsigned int pal_surface_palette_version = 0; -/** 32-bit in-memory backbuffer surface */ -SDL_Surface *surface; +/** 24-bit renderer texture surface */ +SDL_Surface *renderer_texture_surface = nullptr; /** 8-bit surface wrapper around #gpBuffer */ SDL_Surface *pal_surface; @@ -58,9 +58,7 @@ void dx_create_back_buffer() void dx_create_primary_surface() { -#ifdef USE_SDL1 - surface = SDL_GetVideoSurface(); -#else +#ifndef USE_SDL1 if (renderer) { int width, height; if (SDL_GetRendererOutputSize(renderer, &width, &height) <= -1) { @@ -69,12 +67,10 @@ void dx_create_primary_surface() Uint32 format; if (SDL_QueryTexture(texture, &format, nullptr, nullptr, nullptr) < 0) ErrSdl(); - surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, SDL_BITSPERPIXEL(format), format); - } else { - surface = SDL_GetWindowSurface(window); + renderer_texture_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, SDL_BITSPERPIXEL(format), format); } #endif - if (surface == NULL) { + if (GetOutputSurface() == nullptr) { ErrSdl(); } } @@ -140,7 +136,7 @@ void dx_cleanup() SDL_FreeSurface(pal_surface); pal_surface = nullptr; SDL_FreePalette(palette); - SDL_FreeSurface(surface); + SDL_FreeSurface(renderer_texture_surface); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); @@ -195,7 +191,7 @@ void BltFast(DWORD dwX, DWORD dwY, LPRECT lpSrcRect) }; // Convert from 8-bit to 32-bit - if (SDL_BlitSurface(pal_surface, &src_rect, surface, &dst_rect) <= -1) { + if (SDL_BlitSurface(pal_surface, &src_rect, GetOutputSurface(), &dst_rect) <= -1) { ErrSdl(); } @@ -204,6 +200,7 @@ void BltFast(DWORD dwX, DWORD dwY, LPRECT lpSrcRect) void RenderPresent() { + SDL_Surface *surface = GetOutputSurface(); assert(!SDL_MUSTLOCK(surface)); if (!bufferUpdated) { diff --git a/SourceX/miniwin/ddraw.cpp b/SourceX/miniwin/ddraw.cpp new file mode 100644 index 000000000..fc9a3774e --- /dev/null +++ b/SourceX/miniwin/ddraw.cpp @@ -0,0 +1,17 @@ +#include "miniwin/ddraw.h" + +namespace dvl { + +extern SDL_Surface *renderer_texture_surface; // defined in dx.cpp + +SDL_Surface *GetOutputSurface() { +#ifdef USE_SDL1 + return SDL_GetVideoSurface(); +#else + if (renderer) + return renderer_texture_surface; + return SDL_GetWindowSurface(window); +#endif +} + +} // namespace dvl diff --git a/SourceX/miniwin/ddraw.h b/SourceX/miniwin/ddraw.h index 9c2d4997c..fb335cda7 100644 --- a/SourceX/miniwin/ddraw.h +++ b/SourceX/miniwin/ddraw.h @@ -7,10 +7,15 @@ extern SDL_Window *window; extern SDL_Renderer *renderer; extern SDL_Texture *texture; -extern SDL_Surface *surface; extern SDL_Palette *palette; extern SDL_Surface *pal_surface; extern unsigned int pal_surface_palette_version; extern bool bufferUpdated; +// Returns: +// SDL1: Video surface. +// SDL2, no upscale: Window surface. +// SDL2, upscale: Renderer texture surface. +SDL_Surface *GetOutputSurface(); + } // namespace dvl diff --git a/SourceX/storm/storm.cpp b/SourceX/storm/storm.cpp index b1d71d1d4..b32ed172c 100644 --- a/SourceX/storm/storm.cpp +++ b/SourceX/storm/storm.cpp @@ -684,7 +684,7 @@ BOOL SVidPlayContinue(void) #ifndef USE_SDL1 if (renderer) { - if (SDL_BlitSurface(SVidSurface, NULL, surface, NULL) <= -1) { + if (SDL_BlitSurface(SVidSurface, NULL, GetOutputSurface(), NULL) <= -1) { SDL_Log(SDL_GetError()); return false; } @@ -716,7 +716,7 @@ BOOL SVidPlayContinue(void) Uint32 format = SDL_GetWindowPixelFormat(window); SDL_Surface *tmp = SDL_ConvertSurfaceFormat(SVidSurface, format, 0); #endif - if (SDL_BlitScaled(tmp, NULL, surface, &pal_surface_offset) <= -1) { + if (SDL_BlitScaled(tmp, NULL, GetOutputSurface(), &pal_surface_offset) <= -1) { SDL_Log(SDL_GetError()); return false; }