From 4c1cd71d4023bee90f5ee3b200ea1b6e76eb0117 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Sun, 8 Sep 2019 22:18:49 -0700 Subject: [PATCH] Improve use of SDL2 textures. Texture formats are now stated explicitly and the backing surfaces are configured to match them. Texture are now explicitly marked as streaming textures, which should improve GPU performance on drivers that care. The texture upload step now respects dirty rectangles. --- sc2/src/libs/graphics/sdl/sdl2_pure.c | 78 +++++++++++++++++++-------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/sc2/src/libs/graphics/sdl/sdl2_pure.c b/sc2/src/libs/graphics/sdl/sdl2_pure.c index ac24f10b1..d30f923b1 100644 --- a/sc2/src/libs/graphics/sdl/sdl2_pure.c +++ b/sc2/src/libs/graphics/sdl/sdl2_pure.c @@ -40,15 +40,15 @@ static int ScreenFilterMode; static TFB_ScaleFunc scaler = NULL; #if SDL_BYTEORDER == SDL_BIG_ENDIAN -#define R_MASK 0xff000000 -#define G_MASK 0x00ff0000 -#define B_MASK 0x0000ff00 -#define A_MASK 0x000000ff -#else -#define R_MASK 0x000000ff -#define G_MASK 0x0000ff00 -#define B_MASK 0x00ff0000 #define A_MASK 0xff000000 +#define B_MASK 0x00ff0000 +#define G_MASK 0x0000ff00 +#define R_MASK 0x000000ff +#else +#define A_MASK 0x000000ff +#define B_MASK 0x0000ff00 +#define G_MASK 0x00ff0000 +#define R_MASK 0xff000000 #endif static void TFB_SDL2_Preprocess (int force_full_redraw, int transition_amount, int fade_amount); @@ -197,7 +197,10 @@ TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height, int toggl SDL_DestroyTexture (SDL2_Screens[i].texture); SDL2_Screens[i].texture = NULL; } - SDL2_Screens[i].texture = SDL_CreateTextureFromSurface (renderer, SDL2_Screens[i].scaled); + SDL2_Screens[i].texture = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STREAMING, ScreenWidth * 2, ScreenHeight * 2); + SDL_LockSurface (SDL2_Screens[i].scaled); + SDL_UpdateTexture (SDL2_Screens[i].texture, NULL, SDL2_Screens[i].scaled->pixels, SDL2_Screens[i].scaled->pitch); + SDL_UnlockSurface (SDL2_Screens[i].scaled); } scaler = Scale_PrepPlatform (flags, SDL2_Screens[0].scaled->format); graphics_backend = &sdl2_scaled_backend; @@ -216,7 +219,10 @@ TFB_Pure_ConfigureVideo (int driver, int flags, int width, int height, int toggl SDL_DestroyTexture (SDL2_Screens[i].texture); SDL2_Screens[i].texture = NULL; } - SDL2_Screens[i].texture = SDL_CreateTextureFromSurface (renderer, SDL_Screens[i]); + SDL2_Screens[i].texture = SDL_CreateTexture (renderer, SDL_PIXELFORMAT_RGBX8888, SDL_TEXTUREACCESS_STREAMING, ScreenWidth, ScreenHeight); + SDL_LockSurface (SDL_Screens[i]); + SDL_UpdateTexture (SDL2_Screens[i].texture, NULL, SDL_Screens[i]->pixels, SDL_Screens[i]->pitch); + SDL_UnlockSurface (SDL_Screens[i]); } scaler = NULL; graphics_backend = &sdl2_unscaled_backend; @@ -260,6 +266,40 @@ TFB_SDL2_UploadTransitionScreen (void) SDL2_Screens[TFB_SCREEN_TRANSITION].dirty = TRUE; } +static void +TFB_SDL2_UpdateTexture (SDL_Texture *dest, SDL_Surface *src, SDL_Rect *rect) +{ + void *pixels = NULL; + int pitch = 0; + SDL_LockSurface (src); + if (!SDL_LockTexture (dest, rect, &pixels, &pitch)) + { + char *srcBytes, *destBytes; + int row, rowsize; + SDL_Rect backup, *r = rect; + if (!r) + { + /* No rectangle specified, use entire surface */ + backup.x = backup.y = 0; + backup.w = src->w; + backup.h = src->h; + r = &backup; + } + /* SDL2 screen surfaces are always 32bpp */ + srcBytes = src->pixels + (src->pitch * r->y) + (r->x * 4); + destBytes = pixels; + rowsize = r->w * 4; + for (row = 0; row < r->h; ++row) + { + memcpy (destBytes, srcBytes, rowsize); + destBytes += pitch; + srcBytes += src->pitch; + } + SDL_UnlockTexture (dest); + } + SDL_UnlockSurface (src); +} + static void TFB_SDL2_ScanLines (void) { @@ -298,14 +338,9 @@ static void TFB_SDL2_Unscaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) { SDL_Texture *texture = SDL2_Screens[screen].texture; - /* TODO: This is better handled with streaming textures and the - * SDL_[Un]Lock_Texture functions. */ if (SDL2_Screens[screen].dirty) { - SDL_Surface *src = SDL_Screens[screen]; - SDL_LockSurface (src); - SDL_UpdateTexture(texture, NULL, src->pixels, src->pitch); - SDL_UnlockSurface (src); + TFB_SDL2_UpdateTexture (texture, SDL_Screens[screen], &SDL2_Screens[screen].updated); } if (a != 255) { @@ -325,15 +360,16 @@ static void TFB_SDL2_Scaled_ScreenLayer (SCREEN screen, Uint8 a, SDL_Rect *rect) { SDL_Texture *texture = SDL2_Screens[screen].texture; - /* TODO: This is better handled with streaming textures and the - * SDL_[Un]Lock_Texture functions. */ if (SDL2_Screens[screen].dirty) { SDL_Surface *src = SDL2_Screens[screen].scaled; + SDL_Rect scaled_update = SDL2_Screens[screen].updated; scaler (SDL_Screens[screen], src, &SDL2_Screens[screen].updated); - SDL_LockSurface (src); - SDL_UpdateTexture(texture, NULL, src->pixels, src->pitch); - SDL_UnlockSurface (src); + scaled_update.x *= 2; + scaled_update.y *= 2; + scaled_update.w *= 2; + scaled_update.h *= 2; + TFB_SDL2_UpdateTexture (texture, src, &scaled_update); } if (a != 255) {