Skip to content

Commit 24945da

Browse files
committed
id_vl_sdl3: Use SDL3's texture palette support where available
SDL 3.4.0+ is introducing support for palettized textures (at last!): libsdl-org/SDL@0b4b254 libsdl-org/SDL#6192 This allows us to do the palette resolution on the GPU (or at least, in the SDL library), instead of manually doing it ourselves, putting the SDL3 render backend on par with the OpenGL/Vulkan/SDL3_GPU backends. Further work will explore using the 'pixel art' scaling mode. Note that building with SDL 3.4.0+ will require SDL 3.4.0+ at runtime. In the process, fix a few small leaks/errors, too.
1 parent d9617fa commit 24945da

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

src/id_vl_sdl3.c

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#include "assert.h"
21
#include <SDL3/SDL.h>
32
#include <string.h>
43
#include "id_vl.h"
54
#include "id_vl_private.h"
5+
#include "id_us.h"
66
#include "ck_cross.h"
77

88
// We need the window to be exported so we can access it in ID_IN.
@@ -13,6 +13,12 @@ static SDL_Palette *vl_sdl3_palette;
1313
static SDL_Surface *vl_sdl3_stagingSurface;
1414
static SDL_Texture *vl_sdl3_scaledTarget;
1515
static bool vl_sdl3_bilinearSupport = true;
16+
// Should we resolve the palette on the CPU (as is required pre-SDL-3.4.0)
17+
#if SDL_VERSION_ATLEAST(3,4,0)
18+
static bool vl_sdl3_swPalette = false;
19+
#else
20+
static bool vl_sdl3_swPalette = true;
21+
#endif
1622

1723
static void VL_SDL3_ResizeWindow()
1824
{
@@ -84,14 +90,26 @@ static void VL_SDL3_SetVideoMode(int mode)
8490
if (!vl_isIntegerScaled && !vl_sdl3_bilinearSupport)
8591
CK_Cross_LogMessage(CK_LOG_MSG_WARNING, "Using SDL3 software renderer without integer scaling. Pixel size may be inconsistent.\n");
8692

87-
vl_sdl3_texture = SDL_CreateTexture(vl_sdl3_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, VL_EGAVGA_GFX_WIDTH, VL_EGAVGA_GFX_HEIGHT);
88-
SDL_SetTextureScaleMode(vl_sdl3_texture, SDL_SCALEMODE_NEAREST);
93+
if (vl_sdl3_swPalette)
94+
{
95+
vl_sdl3_texture = SDL_CreateTexture(vl_sdl3_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, VL_EGAVGA_GFX_WIDTH, VL_EGAVGA_GFX_HEIGHT);
96+
SDL_SetTextureScaleMode(vl_sdl3_texture, SDL_SCALEMODE_NEAREST);
97+
// As we can't do on-GPU palette conversions with SDL3,
98+
// we do a PAL8->RGBA conversion of the visible area to this surface each frame.
99+
vl_sdl3_stagingSurface = SDL_CreateSurface(VL_EGAVGA_GFX_WIDTH, VL_EGAVGA_GFX_HEIGHT, SDL_PIXELFORMAT_RGBA8888);
100+
}
101+
else
102+
{
103+
#if SDL_VERSION_ATLEAST(3,4,0)
104+
vl_sdl3_texture = SDL_CreateTexture(vl_sdl3_renderer, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STREAMING, VL_EGAVGA_GFX_WIDTH, VL_EGAVGA_GFX_HEIGHT);
105+
SDL_SetTextureScaleMode(vl_sdl3_texture, SDL_SCALEMODE_NEAREST);
106+
#else
107+
Quit("This build requires SDL 3.4.0 or newer!");
108+
#endif
109+
}
89110

90111
vl_sdl3_palette = SDL_CreatePalette(256);
91112

92-
// As we can't do on-GPU palette conversions with SDL3,
93-
// we do a PAL8->RGBA conversion of the visible area to this surface each frame.
94-
vl_sdl3_stagingSurface = SDL_CreateSurface(VL_EGAVGA_GFX_WIDTH, VL_EGAVGA_GFX_HEIGHT, SDL_PIXELFORMAT_RGBA8888);
95113

96114
VL_SDL3_ResizeWindow();
97115
SDL_HideCursor();
@@ -116,7 +134,8 @@ static void *VL_SDL3_CreateSurface(int w, int h, VL_SurfaceUsage usage)
116134

117135
static void VL_SDL3_DestroySurface(void *surface)
118136
{
119-
//TODO: Implement
137+
SDL_Surface *surf = (SDL_Surface *)surface;
138+
SDL_DestroySurface(surf);
120139
}
121140

122141
static long VL_SDL3_GetSurfaceMemUse(void *surface)
@@ -189,8 +208,6 @@ static void VL_SDL3_SurfaceRect_PM(void *dst_surface, int x, int y, int w, int h
189208

190209
static void VL_SDL3_SurfaceToSurface(void *src_surface, void *dst_surface, int x, int y, int sx, int sy, int sw, int sh)
191210
{
192-
// Sadly we cannot naively use SDL_BlitSurface, since the surfaces may
193-
// both be 8-bit but with different palettes, which we ignore.
194211
SDL_Surface *surf = (SDL_Surface *)src_surface;
195212
SDL_Surface *dest = (SDL_Surface *)dst_surface;
196213

@@ -334,10 +351,22 @@ static void VL_SDL3_Present(void *surface, int scrlX, int scrlY, bool singleBuff
334351
SDL_Rect fullRect = {(Sint16)vl_fullRgn_x, (Sint16)vl_fullRgn_y, vl_fullRgn_w, vl_fullRgn_h};
335352
SDL_FRect fullRectF = {(float)vl_fullRgn_x, (float)vl_fullRgn_y, (float)vl_fullRgn_w, (float)vl_fullRgn_h};
336353

337-
SDL_BlitSurface(surf, &srcr, vl_sdl3_stagingSurface, 0);
338-
SDL_LockSurface(vl_sdl3_stagingSurface);
339-
SDL_UpdateTexture(vl_sdl3_texture, 0, vl_sdl3_stagingSurface->pixels, vl_sdl3_stagingSurface->pitch);
340-
SDL_UnlockSurface(vl_sdl3_stagingSurface);
354+
if (vl_sdl3_swPalette)
355+
{
356+
SDL_BlitSurface(surf, &srcr, vl_sdl3_stagingSurface, 0);
357+
SDL_LockSurface(vl_sdl3_stagingSurface);
358+
SDL_UpdateTexture(vl_sdl3_texture, 0, vl_sdl3_stagingSurface->pixels, vl_sdl3_stagingSurface->pitch);
359+
SDL_UnlockSurface(vl_sdl3_stagingSurface);
360+
}
361+
#if SDL_VERSION_ATLEAST(3,4,0)
362+
else
363+
{
364+
SDL_LockSurface(surf);
365+
SDL_UpdateTexture(vl_sdl3_texture, 0, (uint8_t *)surf->pixels + (scrlY * surf->pitch) + scrlX, surf->pitch);
366+
SDL_UnlockSurface(surf);
367+
SDL_SetTexturePalette(vl_sdl3_texture, vl_sdl3_palette);
368+
}
369+
#endif
341370
if (vl_sdl3_scaledTarget)
342371
{
343372
SDL_SetRenderTarget(vl_sdl3_renderer, vl_sdl3_scaledTarget);

0 commit comments

Comments
 (0)