1
0
Fork 0

Replace Lock/UnlockTexture with UpdateTexture

Lock/UnlockTexture is stable and works very well on Linux and with
OpenGL texture driver and on Linux and Windows, but it's usage caused
problems with content of updated texture when used with drivers:
'direct3d11' on Windows and 'metal' on macOS.

Also, Lock/Unlock turned out to be the root cause of deadlocks for
'opengl' driver on AmigaOS.

According to SDL2 documentation, using Lock/UnlockTexture is supposed to
be faster, but in DOSBox usecase we couldn't confirm significant
performance change - there are some community reports indicating, that
UpdateTexture might be actually faster (but we couldn't confirm it
either).

Discussion on this topic can be found on SDL forum:
https://forums.libsdl.org/viewtopic.php?t=9728

In our case, switch to UpdateTexture has no serious negative impact, but
makes the behaviour more robust across the board.
This commit is contained in:
Patryk Obara 2020-03-13 18:01:49 +01:00 committed by Patryk Obara
parent fa4e8c28de
commit 54a50d4231

View file

@ -221,6 +221,7 @@ enum PRIORITY_LEVELS {
PRIORITY_LEVEL_HIGHEST
};
struct SDL_Block {
bool inited;
bool active; //If this isn't set don't draw
@ -293,6 +294,7 @@ struct SDL_Block {
const char *rendererDriver;
int displayNumber;
struct {
SDL_Surface *input_surface = nullptr;
SDL_Texture *texture = nullptr;
SDL_PixelFormat *pixelFormat = nullptr;
} texture;
@ -988,6 +990,7 @@ dosurface:
rendering drivers, "opengles" being a notable exception */
sdl.texture.texture = SDL_CreateTexture(sdl.renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, width, height);
/* SDL_PIXELFORMAT_ABGR8888 (not RGB) is the
only supported format for the "opengles" driver */
if (!sdl.texture.texture) {
@ -1001,6 +1004,13 @@ dosurface:
LOG_MSG("SDL:Can't create texture, falling back to surface");
goto dosurface;
}
sdl.texture.input_surface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
if (!sdl.texture.input_surface) {
LOG_MSG("SDL: Error while preparing texture input");
goto dosurface;
}
SDL_SetRenderDrawColor(sdl.renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
sdl.desktop.type=SCREEN_TEXTURE;
Uint32 pixelFormat;
@ -1408,7 +1418,6 @@ bool GFX_StartUpdate(uint8_t * &pixels, int &pitch)
if (!sdl.active || sdl.updating)
return false;
void *tex_pixels = nullptr;
switch (sdl.desktop.type) {
case SCREEN_SURFACE:
pixels = static_cast<uint8_t *>(sdl.surface->pixels);
@ -1420,9 +1429,9 @@ bool GFX_StartUpdate(uint8_t * &pixels, int &pitch)
sdl.updating = true;
return true;
case SCREEN_TEXTURE:
if (SDL_LockTexture(sdl.texture.texture, nullptr, &tex_pixels, &pitch) < 0)
return false;
pixels = static_cast<uint8_t *>(tex_pixels);
assert(sdl.texture.input_surface);
pixels = static_cast<uint8_t *>(sdl.texture.input_surface->pixels);
pitch = sdl.texture.input_surface->pitch;
sdl.updating = true;
return true;
#if C_OPENGL
@ -1475,7 +1484,11 @@ void GFX_EndUpdate( const Bit16u *changedLines ) {
}
break;
case SCREEN_TEXTURE:
SDL_UnlockTexture(sdl.texture.texture);
assert(sdl.texture.input_surface);
SDL_UpdateTexture(sdl.texture.texture,
nullptr, // update entire texture
sdl.texture.input_surface->pixels,
sdl.texture.input_surface->pitch);
SDL_RenderClear(sdl.renderer);
SDL_RenderCopy(sdl.renderer, sdl.texture.texture, NULL, &sdl.clip);
SDL_RenderPresent(sdl.renderer);
@ -1592,6 +1605,10 @@ static void CleanupSDLResources()
SDL_DestroyTexture(sdl.texture.texture);
sdl.texture.texture = nullptr;
}
if (sdl.texture.input_surface) {
SDL_FreeSurface(sdl.texture.input_surface);
sdl.texture.input_surface = nullptr;
}
if (sdl.renderer) {
SDL_DestroyRenderer(sdl.renderer);
sdl.renderer = nullptr;