WIP: port renderer + supporting layers to SDL 3 (builds clean)
Completes phases 3-6 of the migration plan. After this commit, the
codebase compiles and links against pure SDL 3 (no compat shim). The
binary is unverified at runtime but the build is clean.
Renderer (graphics/gfxengine.{cpp,h}):
- Replace SDL_SetVideoMode + SDL_Flip + page-flip machinery with
SDL_CreateWindow + SDL_CreateRenderer + a streaming SDL_Texture.
The CPU-side back buffer (softbuf) is now always ARGB8888; legacy
HW/double-buffer/page flags are dead.
- flip() does a single full-frame SDL_UpdateTexture + SDL_RenderClear
+ SDL_RenderTexture + SDL_RenderPresent each frame. The dirtyrect
iteration is retained only to drive widget phys_refresh() callbacks.
- SDL_SetRenderLogicalPresentation gives us letterbox scaling for free.
- SDL_SetRenderVSync replaces glSDL_VSync.
- title()/cursor() ported to SDL 3 window/cursor APIs.
Surface API (graphics/sprite.c, filters.c, window.cpp, sofont.cpp,
region.c):
- SDL_FreeSurface → SDL_DestroySurface
- SDL_FillRect → SDL_FillSurfaceRect
- SDL_SetClipRect → SDL_SetSurfaceClipRect
- SDL_SetColorKey(s, flags, key) → SDL_SetSurfaceColorKey(s, bool, key)
- SDL_SetAlpha(s, flags, a) → SDL_SetSurfaceAlphaMod + BlendMode
- SDL_SetColors → SDL_SetSurfacePalette
- SDL_CreateRGBSurface(...) → SDL_CreateSurface(w, h, format_enum)
- SDL_DisplayFormat[Alpha] → SDL_ConvertSurface(s, ARGB8888)
- SDL_MapRGB(surf->format, ...) → SDL_MapSurfaceRGB(surf, ...)
- surface->format->Field → SDL_GetPixelFormatDetails(surf->format)->field
- surface->format->Amask test → SDL_ISPIXELFORMAT_ALPHA
- surface->clip_rect → SDL_GetSurfaceClipRect
Events (kobo.cpp):
- SDL_{KEYDOWN,KEYUP,QUIT,VIDEOEXPOSE,MOUSE*,JOY*} → SDL_EVENT_*
- SDL_ACTIVEEVENT (with gain check) → SDL_EVENT_WINDOW_FOCUS_LOST
- ev.key.keysym.sym → ev.key.key (.unicode → text input, deferred)
- SDLK_PRINT/SYSREQ → SDLK_PRINTSCREEN; lowercase SDLK_p/y/n → uppercase
- ev.motion.x/y for button events → ev.button.x/y (struct layout differs)
- KMOD_META → SDL_KMOD_GUI
- SDL_INIT_NOPARACHUTE → SDL_Init(0) (no parachute by default in SDL 3)
Keymap (gamectl.{cpp,h}):
- SDLKey → SDL_Keycode
- SDLK_KP{1..9} → SDLK_KP_{1..9}
Stubs deferred for later phases (binary will run but with degraded
behavior):
- sound/audio.c: _start_SDL_output returns -1 immediately; SDL 1.2
audio callback model needs full rewrite onto SDL_AudioStream.
- kobo.cpp init_js/close_js: SDL 3 joystick API uses instance IDs;
re-port deferred.
- states.cpp SDL_WM_GrabInput/SDL_EnableUNICODE: need window pointer
exposed from gfxengine; stubbed.
- gamectl.cpp SDL_EnableKeyRepeat: removed; relies on ev.key.repeat.
Other adjustments:
- options.cpp: GFX_DRIVER_GLSDL menu paths removed; show vsync option
always (renderer handles it).
- sound/a_wave.c: AUDIO_S8/AUDIO_S16SYS → SDL_AUDIO_S8/S16, SDL_FreeWAV
→ SDL_free.
- gfxengine.cpp: SDL_putenv("SDL_VIDEO_CENTERED=1") obsolete (handled
by SDL_CreateWindow defaults).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+34
-53
@@ -235,33 +235,17 @@ int s_filter_rgba8(s_bank_t *b, unsigned first, unsigned frames,
|
||||
s_filter_args_t *args)
|
||||
{
|
||||
unsigned i;
|
||||
SDL_PixelFormat fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.BitsPerPixel = 32;
|
||||
fmt.BytesPerPixel = 4;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
fmt.Rmask = 0xff000000;
|
||||
fmt.Gmask = 0x00ff0000;
|
||||
fmt.Bmask = 0x0000ff00;
|
||||
fmt.Amask = 0x000000ff;
|
||||
#else
|
||||
fmt.Rmask = 0x000000ff;
|
||||
fmt.Gmask = 0x0000ff00;
|
||||
fmt.Bmask = 0x00ff0000;
|
||||
fmt.Amask = 0xff000000;
|
||||
#endif
|
||||
for(i = 0; i < frames; ++i)
|
||||
{
|
||||
SDL_Surface *tmp;
|
||||
s_sprite_t *s = s_get_sprite_b(b, first+i);
|
||||
if(!s)
|
||||
continue;
|
||||
tmp = SDL_ConvertSurface(s->surface, &fmt,
|
||||
SDL_SWSURFACE);
|
||||
tmp = SDL_ConvertSurface(s->surface, SDL_PIXELFORMAT_RGBA32);
|
||||
if(!tmp)
|
||||
return -1;
|
||||
|
||||
SDL_FreeSurface(s->surface);
|
||||
SDL_DestroySurface(s->surface);
|
||||
s->surface = tmp;
|
||||
}
|
||||
return 0;
|
||||
@@ -289,7 +273,7 @@ int s_filter_dither(s_bank_t *b, unsigned first, unsigned frames,
|
||||
switch (s_blitmode)
|
||||
{
|
||||
case S_BLITMODE_AUTO:
|
||||
if(s->surface->format->Amask)
|
||||
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
|
||||
ar = ag = ab = 8;
|
||||
break;
|
||||
case S_BLITMODE_OPAQUE:
|
||||
@@ -458,7 +442,8 @@ int s_filter_dither(s_bank_t *b, unsigned first, unsigned frames,
|
||||
static void tweak_ck(SDL_Surface *s)
|
||||
{
|
||||
int x, y;
|
||||
if(s->format->BitsPerPixel != 32)
|
||||
const SDL_PixelFormatDetails *fmt = SDL_GetPixelFormatDetails(s->format);
|
||||
if(!fmt || fmt->bits_per_pixel != 32)
|
||||
return;
|
||||
for(y = 0; y < s->h; ++y)
|
||||
{
|
||||
@@ -488,53 +473,54 @@ int s_filter_displayformat(s_bank_t * b, unsigned first, unsigned frames,
|
||||
switch(s_blitmode)
|
||||
{
|
||||
case S_BLITMODE_AUTO:
|
||||
if(s->surface->format->Amask)
|
||||
SDL_SetAlpha(s->surface,
|
||||
SDL_SRCALPHA |
|
||||
SDL_RLEACCEL,
|
||||
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
|
||||
{
|
||||
SDL_SetSurfaceAlphaMod(s->surface,
|
||||
SDL_ALPHA_OPAQUE);
|
||||
SDL_SetSurfaceBlendMode(s->surface,
|
||||
SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
else
|
||||
SDL_SetColorKey(s->surface, SDL_RLEACCEL, 0);
|
||||
SDL_SetSurfaceColorKey(s->surface, false, 0);
|
||||
break;
|
||||
case S_BLITMODE_OPAQUE:
|
||||
SDL_SetColorKey(s->surface, SDL_RLEACCEL, 0);
|
||||
SDL_SetSurfaceColorKey(s->surface, false, 0);
|
||||
break;
|
||||
case S_BLITMODE_COLORKEY:
|
||||
SDL_SetColorKey(s->surface,
|
||||
SDL_SRCCOLORKEY | SDL_RLEACCEL,
|
||||
SDL_MapRGB(s->surface->format,
|
||||
SDL_SetSurfaceColorKey(s->surface, true,
|
||||
SDL_MapSurfaceRGB(s->surface,
|
||||
s_colorkey.r,
|
||||
s_colorkey.g,
|
||||
s_colorkey.b));
|
||||
break;
|
||||
case S_BLITMODE_ALPHA:
|
||||
SDL_SetAlpha(s->surface,
|
||||
SDL_SRCALPHA | SDL_RLEACCEL,
|
||||
s_alpha);
|
||||
SDL_SetSurfaceAlphaMod(s->surface, s_alpha);
|
||||
SDL_SetSurfaceBlendMode(s->surface,
|
||||
SDL_BLENDMODE_BLEND);
|
||||
break;
|
||||
}
|
||||
|
||||
// SDL 3 dropped SDL_DisplayFormat. We always convert sprites
|
||||
// to the back-buffer format (ARGB8888); see gfxengine.cpp.
|
||||
if(args->x)
|
||||
{
|
||||
if(s->surface->format->Amask)
|
||||
if(SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
|
||||
tweak_ck(s->surface);
|
||||
tmp = SDL_DisplayFormat(s->surface);
|
||||
if(s->surface->format->Amask)
|
||||
SDL_SetColorKey(tmp,
|
||||
SDL_SRCCOLORKEY | SDL_RLEACCEL,
|
||||
SDL_MapRGB(tmp->format, 0,0,0));
|
||||
tmp = SDL_ConvertSurface(s->surface,
|
||||
SDL_PIXELFORMAT_ARGB8888);
|
||||
if(tmp && SDL_ISPIXELFORMAT_ALPHA(s->surface->format))
|
||||
SDL_SetSurfaceColorKey(tmp, true,
|
||||
SDL_MapSurfaceRGB(tmp, 0,0,0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(s->surface->format->Amask)
|
||||
tmp = SDL_DisplayFormatAlpha(s->surface);
|
||||
else
|
||||
tmp = SDL_DisplayFormat(s->surface);
|
||||
tmp = SDL_ConvertSurface(s->surface,
|
||||
SDL_PIXELFORMAT_ARGB8888);
|
||||
}
|
||||
if(!tmp)
|
||||
return -1;
|
||||
|
||||
SDL_FreeSurface(s->surface);
|
||||
SDL_DestroySurface(s->surface);
|
||||
s->surface = tmp;
|
||||
}
|
||||
return 0;
|
||||
@@ -900,18 +886,13 @@ int s_filter_scale(s_bank_t *b, unsigned first, unsigned frames,
|
||||
if(!s)
|
||||
continue;
|
||||
params.src = s->surface;
|
||||
params.dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
params.max_x, params.max_y, 32,
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||
#else
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
|
||||
#endif
|
||||
params.dst = SDL_CreateSurface(params.max_x, params.max_y,
|
||||
SDL_PIXELFORMAT_RGBA32);
|
||||
if(!params.dst)
|
||||
return -1;
|
||||
#ifdef DEBUG
|
||||
SDL_FillRect(params.dst, NULL,
|
||||
SDL_MapRGB(params.dst->format, 255, 128, 0));
|
||||
SDL_FillSurfaceRect(params.dst, NULL,
|
||||
SDL_MapSurfaceRGB(params.dst, 255, 128, 0));
|
||||
#endif
|
||||
|
||||
/* Deal with SFont marker row */
|
||||
@@ -957,7 +938,7 @@ int s_filter_scale(s_bank_t *b, unsigned first, unsigned frames,
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(s->surface);
|
||||
SDL_DestroySurface(s->surface);
|
||||
s->surface = params.dst;
|
||||
}
|
||||
b->w = params.max_x;
|
||||
|
||||
+115
-140
@@ -40,6 +40,9 @@ gfxengine_t::gfxengine_t()
|
||||
{
|
||||
gfxengine = this; /* Uurgh! Kludge. */
|
||||
|
||||
sdl_window = NULL;
|
||||
sdl_renderer = NULL;
|
||||
fb_texture = NULL;
|
||||
screen_surface = NULL;
|
||||
softbuf = NULL;
|
||||
fullwin = NULL;
|
||||
@@ -443,10 +446,13 @@ void gfxengine_t::dither(int type, int _broken_rgba8)
|
||||
|
||||
if(_dither)
|
||||
{
|
||||
// SDL 3: back buffer is always ARGB8888 (8 bits per channel,
|
||||
// no loss). The legacy formula was 1 << (Rloss - 1); for 8 bpc
|
||||
// the dithering amplitude collapses to 0.
|
||||
df->args.x = 0;
|
||||
df->args.r = 1<<(screen_surface->format->Rloss-1);
|
||||
df->args.g = 1<<(screen_surface->format->Gloss-1);
|
||||
df->args.b = 1<<(screen_surface->format->Bloss-1);
|
||||
df->args.r = 0;
|
||||
df->args.g = 0;
|
||||
df->args.b = 0;
|
||||
}
|
||||
else
|
||||
df->args.x = df->args.r = df->args.g = df->args.b = 0;
|
||||
@@ -732,8 +738,8 @@ void gfxengine_t::title(const char *win, const char *icon)
|
||||
{
|
||||
_title = win;
|
||||
_icontitle = icon;
|
||||
if(screen_surface)
|
||||
SDL_WM_SetCaption(_title, _icontitle);
|
||||
if(sdl_window)
|
||||
SDL_SetWindowTitle(sdl_window, _title);
|
||||
}
|
||||
|
||||
|
||||
@@ -743,97 +749,94 @@ void gfxengine_t::title(const char *win, const char *icon)
|
||||
|
||||
int gfxengine_t::show()
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if(!is_open)
|
||||
return -1;
|
||||
|
||||
if(is_showing)
|
||||
return 0;
|
||||
|
||||
if(_centered && !_fullscreen)
|
||||
SDL_putenv((char *)"SDL_VIDEO_CENTERED=1");
|
||||
|
||||
log_printf(DLOG, "Opening screen...\n");
|
||||
if(!SDL_WasInit(SDL_INIT_VIDEO))
|
||||
if(SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
|
||||
if(!SDL_InitSubSystem(SDL_INIT_VIDEO))
|
||||
{
|
||||
log_printf(ELOG, "Failed to initialize SDL!\n");
|
||||
log_printf(ELOG, "Failed to initialize SDL: %s\n",
|
||||
SDL_GetError());
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(_doublebuf)
|
||||
flags |= SDL_DOUBLEBUF | SDL_HWSURFACE;
|
||||
else
|
||||
{
|
||||
if(!_shadow)
|
||||
flags |= SDL_HWSURFACE;
|
||||
}
|
||||
|
||||
// SDL 3 window + renderer model.
|
||||
//
|
||||
// The kobo engine renders into a CPU-side back buffer (softbuf) via
|
||||
// SDL_BlitSurface/SDL_FillSurfaceRect, and uploads the result to a
|
||||
// streaming SDL_Texture once per frame. This preserves the entire
|
||||
// software-compositing code path inherited from SDL 1.2 (window.cpp,
|
||||
// sprite.c, filters.c, sofont.cpp), while letting the GPU handle
|
||||
// scaling and presentation. SDL_DOUBLEBUF / SDL_HWSURFACE / page-
|
||||
// flipping flags are obsolete and ignored.
|
||||
Uint64 win_flags = 0;
|
||||
if(_fullscreen)
|
||||
flags |= SDL_FULLSCREEN;
|
||||
win_flags |= SDL_WINDOW_FULLSCREEN;
|
||||
|
||||
flags |= xflags;
|
||||
|
||||
screen_surface = SDL_SetVideoMode(_width, _height, _depth, flags);
|
||||
if(!screen_surface)
|
||||
sdl_window = SDL_CreateWindow(_title ? _title : "Kobo Deluxe",
|
||||
_width, _height, win_flags);
|
||||
if(!sdl_window)
|
||||
{
|
||||
log_printf(ELOG, "Failed to open display!\n");
|
||||
log_printf(ELOG, "Failed to open window: %s\n", SDL_GetError());
|
||||
return -3;
|
||||
}
|
||||
|
||||
if((screen_surface->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
|
||||
sdl_renderer = SDL_CreateRenderer(sdl_window, NULL);
|
||||
if(!sdl_renderer)
|
||||
{
|
||||
if(!_doublebuf)
|
||||
{
|
||||
log_printf(WLOG, "Could not get"
|
||||
" single buffered display.\n");
|
||||
doublebuffer(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_doublebuf)
|
||||
{
|
||||
log_printf(WLOG, "Could not get"
|
||||
" double buffered display.\n");
|
||||
doublebuffer(0);
|
||||
}
|
||||
log_printf(ELOG, "Failed to create renderer: %s\n",
|
||||
SDL_GetError());
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
sdl_window = NULL;
|
||||
return -4;
|
||||
}
|
||||
|
||||
if((screen_surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE)
|
||||
// Letterbox the back buffer when the window is resized / fullscreen.
|
||||
SDL_SetRenderLogicalPresentation(sdl_renderer, _width, _height,
|
||||
SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||
SDL_SetRenderVSync(sdl_renderer, _vsync ? 1 : 0);
|
||||
|
||||
// The back buffer is always a CPU-side ARGB8888 surface.
|
||||
softbuf = SDL_CreateSurface(_width, _height, SDL_PIXELFORMAT_ARGB8888);
|
||||
if(!softbuf)
|
||||
{
|
||||
if(_shadow)
|
||||
{
|
||||
softbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
_width, _height,
|
||||
screen_surface->format->BitsPerPixel,
|
||||
screen_surface->format->Rmask,
|
||||
screen_surface->format->Gmask,
|
||||
screen_surface->format->Bmask,
|
||||
screen_surface->format->Amask);
|
||||
if(!softbuf)
|
||||
{
|
||||
log_printf(WLOG, "Failed to create shadow buffer! "
|
||||
"Trying direct rendering.\n");
|
||||
shadow(0);
|
||||
}
|
||||
}
|
||||
log_printf(ELOG, "Failed to create back buffer: %s\n",
|
||||
SDL_GetError());
|
||||
SDL_DestroyRenderer(sdl_renderer);
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
sdl_renderer = NULL;
|
||||
sdl_window = NULL;
|
||||
return -5;
|
||||
}
|
||||
else
|
||||
screen_surface = softbuf; // alias for legacy code paths
|
||||
|
||||
fb_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING, _width, _height);
|
||||
if(!fb_texture)
|
||||
{
|
||||
if(_shadow)
|
||||
log_printf(WLOG, "Shadow buffer requested; "
|
||||
"relying on SDL's shadow buffer.\n");
|
||||
else
|
||||
{
|
||||
log_printf(WLOG, "Could not get h/w display surface.\n");
|
||||
shadow(0); //...which means we're using SDL's shadow.
|
||||
}
|
||||
log_printf(ELOG, "Failed to create framebuffer texture: %s\n",
|
||||
SDL_GetError());
|
||||
SDL_DestroySurface(softbuf);
|
||||
SDL_DestroyRenderer(sdl_renderer);
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
softbuf = screen_surface = NULL;
|
||||
sdl_renderer = NULL;
|
||||
sdl_window = NULL;
|
||||
return -6;
|
||||
}
|
||||
SDL_SetTextureScaleMode(fb_texture,
|
||||
(_scalemode == GFX_SCALE_NEAREST) ?
|
||||
SDL_SCALEMODE_NEAREST : SDL_SCALEMODE_LINEAR);
|
||||
|
||||
if(_cursor)
|
||||
SDL_ShowCursor();
|
||||
else
|
||||
SDL_HideCursor();
|
||||
|
||||
SDL_WM_SetCaption(_title, _icontitle);
|
||||
SDL_ShowCursor(_cursor);
|
||||
cs_engine_set_size(csengine, _width, _height);
|
||||
csengine->filter = use_interpolation;
|
||||
|
||||
@@ -886,12 +889,27 @@ void gfxengine_t::hide(void)
|
||||
w = w->next;
|
||||
}
|
||||
|
||||
if(fb_texture)
|
||||
{
|
||||
SDL_DestroyTexture(fb_texture);
|
||||
fb_texture = NULL;
|
||||
}
|
||||
if(softbuf)
|
||||
{
|
||||
SDL_FreeSurface(softbuf);
|
||||
SDL_DestroySurface(softbuf);
|
||||
softbuf = NULL;
|
||||
}
|
||||
screen_surface = NULL;
|
||||
if(sdl_renderer)
|
||||
{
|
||||
SDL_DestroyRenderer(sdl_renderer);
|
||||
sdl_renderer = NULL;
|
||||
}
|
||||
if(sdl_window)
|
||||
{
|
||||
SDL_DestroyWindow(sdl_window);
|
||||
sdl_window = NULL;
|
||||
}
|
||||
|
||||
is_showing = 0;
|
||||
}
|
||||
@@ -940,13 +958,15 @@ void gfxengine_t::__invalidate(int page, SDL_Rect *rect, window_t *window)
|
||||
|
||||
/* Clip to screen (stolen from SDL_surface.c) */
|
||||
SDL_Rect dr = *rect;
|
||||
SDL_Rect screen_clip;
|
||||
SDL_GetSurfaceClipRect(screen_surface, &screen_clip);
|
||||
int Amin, Amax, Bmin, Bmax;
|
||||
|
||||
/* Horizontal intersection */
|
||||
Amin = dr.x;
|
||||
Amax = Amin + dr.w;
|
||||
Bmin = screen_surface->clip_rect.x;
|
||||
Bmax = Bmin + screen_surface->clip_rect.w;
|
||||
Bmin = screen_clip.x;
|
||||
Bmax = Bmin + screen_clip.w;
|
||||
if(Bmin > Amin)
|
||||
Amin = Bmin;
|
||||
dr.x = Amin;
|
||||
@@ -957,8 +977,8 @@ void gfxengine_t::__invalidate(int page, SDL_Rect *rect, window_t *window)
|
||||
/* Vertical intersection */
|
||||
Amin = dr.y;
|
||||
Amax = Amin + dr.h;
|
||||
Bmin = screen_surface->clip_rect.y;
|
||||
Bmax = Bmin + screen_surface->clip_rect.h;
|
||||
Bmin = screen_clip.y;
|
||||
Bmax = Bmin + screen_clip.h;
|
||||
if(Bmin > Amin)
|
||||
Amin = Bmin;
|
||||
dr.y = Amin;
|
||||
@@ -1062,7 +1082,12 @@ void gfxengine_t::cursor(int csr)
|
||||
{
|
||||
_cursor = csr;
|
||||
if(screen_surface)
|
||||
SDL_ShowCursor(csr);
|
||||
{
|
||||
if(csr)
|
||||
SDL_ShowCursor();
|
||||
else
|
||||
SDL_HideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1168,8 +1193,8 @@ void gfxengine_t::frame()
|
||||
SDL_Event ev;
|
||||
while(SDL_PollEvent(&ev))
|
||||
{
|
||||
if(ev.type == SDL_KEYDOWN)
|
||||
if(ev.key.keysym.sym == SDLK_ESCAPE)
|
||||
if(ev.type == SDL_EVENT_KEY_DOWN)
|
||||
if(ev.key.key == SDLK_ESCAPE)
|
||||
stop();
|
||||
}
|
||||
}
|
||||
@@ -1236,41 +1261,15 @@ void gfxengine_t::refresh_rect(SDL_Rect *r)
|
||||
|
||||
void gfxengine_t::flip()
|
||||
{
|
||||
if(!screen_surface)
|
||||
if(!screen_surface || !sdl_renderer || !fb_texture)
|
||||
return;
|
||||
|
||||
// Init dirtyrect table flipping, if necessary.
|
||||
switch(_pages)
|
||||
{
|
||||
case -1:
|
||||
if(!_doublebuf)
|
||||
frontpage = backpage = 0;
|
||||
else if(frontpage == backpage)
|
||||
{
|
||||
frontpage = 0;
|
||||
backpage = 1;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
frontpage = backpage = 0;
|
||||
invalidate();
|
||||
break;
|
||||
case 1:
|
||||
frontpage = backpage = 0;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if(frontpage == backpage)
|
||||
{
|
||||
frontpage = 0;
|
||||
backpage = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Process the dirtyrects.
|
||||
int i;
|
||||
for(i = 0; i < dirtyrects[backpage]; ++i)
|
||||
// SDL 3 has no hardware page flipping; we always present one back
|
||||
// buffer per frame. Keep the dirtyrect iteration only to drive the
|
||||
// phys_refresh() callbacks that window widgets rely on; the upload
|
||||
// is a single full-surface copy regardless.
|
||||
frontpage = backpage = 0;
|
||||
for(int i = 0; i < dirtyrects[backpage]; ++i)
|
||||
{
|
||||
if(dirtywtable[backpage][i])
|
||||
{
|
||||
@@ -1282,36 +1281,12 @@ void gfxengine_t::flip()
|
||||
else
|
||||
refresh_rect(&dirtytable[backpage][i]);
|
||||
}
|
||||
dirtyrects[backpage] = 0;
|
||||
|
||||
// Perform the actual flip or update
|
||||
if(_shadow)
|
||||
{
|
||||
for(i = 0; i < dirtyrects[backpage]; ++i)
|
||||
SDL_BlitSurface(softbuf,
|
||||
&dirtytable[backpage][i],
|
||||
screen_surface,
|
||||
&dirtytable[backpage][i]);
|
||||
}
|
||||
if(_doublebuf)
|
||||
{
|
||||
dirtyrects[backpage] = 0;
|
||||
if(_pages == -1)
|
||||
{
|
||||
backpage = !backpage;
|
||||
frontpage = !frontpage;
|
||||
}
|
||||
else if(_pages > 1)
|
||||
{
|
||||
backpage = (backpage + 1) % _pages;
|
||||
frontpage = (frontpage + 1) % _pages;
|
||||
}
|
||||
SDL_Flip(screen_surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_UpdateRects(screen_surface, dirtyrects[0], dirtytable[0]);
|
||||
dirtyrects[0] = 0;
|
||||
}
|
||||
SDL_UpdateTexture(fb_texture, NULL, softbuf->pixels, softbuf->pitch);
|
||||
SDL_RenderClear(sdl_renderer);
|
||||
SDL_RenderTexture(sdl_renderer, fb_texture, NULL, NULL);
|
||||
SDL_RenderPresent(sdl_renderer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -208,7 +208,10 @@ class gfxengine_t
|
||||
gfx_drivers_t _driver;
|
||||
gfx_scalemodes_t _scalemode;
|
||||
int _clamping;
|
||||
SDL_Surface *screen_surface;
|
||||
SDL_Window *sdl_window;
|
||||
SDL_Renderer *sdl_renderer;
|
||||
SDL_Texture *fb_texture;
|
||||
SDL_Surface *screen_surface; // alias for softbuf in SDL 3
|
||||
SDL_Surface *softbuf;
|
||||
int backpage;
|
||||
int frontpage;
|
||||
|
||||
+11
-2
@@ -44,7 +44,9 @@ static Uint32 gp2(SDL_Surface *surface, int x, int y)
|
||||
|
||||
static Uint32 gp3(SDL_Surface *surface, int x, int y)
|
||||
{
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
const SDL_PixelFormatDetails *fmt =
|
||||
SDL_GetPixelFormatDetails(surface->format);
|
||||
int bpp = fmt ? fmt->bytes_per_pixel : 3;
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
return p[0] << 16 | p[1] << 8 | p[2];
|
||||
@@ -74,7 +76,14 @@ RGN_region *RGN_ScanMask(SDL_Surface *src, Uint32 key)
|
||||
RGN_FreeRegion(rgn);
|
||||
return NULL;
|
||||
}
|
||||
switch(src->format->BytesPerPixel)
|
||||
const SDL_PixelFormatDetails *src_fmt =
|
||||
SDL_GetPixelFormatDetails(src->format);
|
||||
if(!src_fmt)
|
||||
{
|
||||
RGN_FreeRegion(rgn);
|
||||
return NULL;
|
||||
}
|
||||
switch(src_fmt->bytes_per_pixel)
|
||||
{
|
||||
case 1:
|
||||
gp = gp1;
|
||||
|
||||
+27
-16
@@ -20,7 +20,7 @@ SoFont::SoFont()
|
||||
SoFont::~SoFont()
|
||||
{
|
||||
if(picture)
|
||||
SDL_FreeSurface(picture);
|
||||
SDL_DestroySurface(picture);
|
||||
delete[]CharPos;
|
||||
delete[]CharOffset;
|
||||
delete[]Spacing;
|
||||
@@ -45,7 +45,11 @@ namespace SoFontUtilities
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bpp = Surface->format->BytesPerPixel;
|
||||
const SDL_PixelFormatDetails *fmt =
|
||||
SDL_GetPixelFormatDetails(Surface->format);
|
||||
if(!fmt)
|
||||
return 0;
|
||||
Bpp = fmt->bytes_per_pixel;
|
||||
|
||||
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
|
||||
X * Bpp;
|
||||
@@ -63,10 +67,10 @@ namespace SoFontUtilities
|
||||
case 3:
|
||||
// Format/endian independent
|
||||
Uint8 r, g, b;
|
||||
r = *((bits) + Surface->format->Rshift / 8);
|
||||
g = *((bits) + Surface->format->Gshift / 8);
|
||||
b = *((bits) + Surface->format->Bshift / 8);
|
||||
return SDL_MapRGB(Surface->format, r, g, b);
|
||||
r = *((bits) + fmt->Rshift / 8);
|
||||
g = *((bits) + fmt->Gshift / 8);
|
||||
b = *((bits) + fmt->Bshift / 8);
|
||||
return SDL_MapSurfaceRGB(Surface, r, g, b);
|
||||
break;
|
||||
case 4:
|
||||
return *((Uint32 *) Surface->pixels +
|
||||
@@ -94,7 +98,11 @@ namespace SoFontUtilities
|
||||
return;
|
||||
}
|
||||
|
||||
Bpp = Surface->format->BytesPerPixel;
|
||||
const SDL_PixelFormatDetails *fmt =
|
||||
SDL_GetPixelFormatDetails(Surface->format);
|
||||
if(!fmt)
|
||||
return;
|
||||
Bpp = fmt->bytes_per_pixel;
|
||||
|
||||
bits = ((Uint8 *) Surface->pixels) + Y * Surface->pitch +
|
||||
X * Bpp;
|
||||
@@ -113,10 +121,11 @@ namespace SoFontUtilities
|
||||
case 3:
|
||||
// Format/endian independent
|
||||
Uint8 r, g, b;
|
||||
SDL_GetRGB(c, Surface->format, &r, &g, &b);
|
||||
*((bits) + Surface->format->Rshift / 8) = r;
|
||||
*((bits) + Surface->format->Gshift / 8) = g;
|
||||
*((bits) + Surface->format->Bshift / 8) = b;
|
||||
SDL_GetRGB(c, fmt, SDL_GetSurfacePalette(Surface),
|
||||
&r, &g, &b);
|
||||
*((bits) + fmt->Rshift / 8) = r;
|
||||
*((bits) + fmt->Gshift / 8) = g;
|
||||
*((bits) + fmt->Bshift / 8) = b;
|
||||
break;
|
||||
case 4:
|
||||
*((Uint32 *) Surface->pixels +
|
||||
@@ -224,7 +233,7 @@ bool SoFont::DoStartNewChar(Sint32 x)
|
||||
if(!picture)
|
||||
return false;
|
||||
return SoFontGetPixel(picture, x, 0) ==
|
||||
SDL_MapRGB(picture->format, 255, 0, 255);
|
||||
SDL_MapSurfaceRGB(picture, 255, 0, 255);
|
||||
}
|
||||
|
||||
void SoFont::CleanSurface()
|
||||
@@ -233,7 +242,7 @@ void SoFont::CleanSurface()
|
||||
return;
|
||||
|
||||
int x = 0, y = 0;
|
||||
Uint32 pix = SDL_MapRGB(picture->format, 255, 0, 255);
|
||||
Uint32 pix = SDL_MapSurfaceRGB(picture, 255, 0, 255);
|
||||
|
||||
while(x < picture->w)
|
||||
{
|
||||
@@ -259,7 +268,7 @@ bool SoFont::load(SDL_Surface * FontSurface)
|
||||
return false;
|
||||
}
|
||||
if(picture)
|
||||
SDL_FreeSurface(picture);
|
||||
SDL_DestroySurface(picture);
|
||||
picture = FontSurface;
|
||||
height = picture->h - 1;
|
||||
while(x < picture->w)
|
||||
@@ -499,8 +508,10 @@ void SoFont::CenteredString(SDL_Surface * Surface, const char *text,
|
||||
{
|
||||
if(!picture)
|
||||
return;
|
||||
CenteredString(Surface, Surface->clip_rect.w / 2,
|
||||
Surface->clip_rect.h / 2, text, clip);
|
||||
SDL_Rect surf_clip;
|
||||
SDL_GetSurfaceClipRect(Surface, &surf_clip);
|
||||
CenteredString(Surface, surf_clip.w / 2,
|
||||
surf_clip.h / 2, text, clip);
|
||||
}
|
||||
|
||||
void SoFont::PutStringCleverCursor(SDL_Surface * Surface, const char *text,
|
||||
|
||||
+38
-29
@@ -177,7 +177,7 @@ s_sprite_t *s_new_sprite_b(s_bank_t *b, unsigned frame)
|
||||
else
|
||||
{
|
||||
if(s->surface)
|
||||
SDL_FreeSurface(s->surface);
|
||||
SDL_DestroySurface(s->surface);
|
||||
s->surface = NULL;
|
||||
}
|
||||
return s;
|
||||
@@ -212,7 +212,7 @@ void s_delete_sprite_b(s_bank_t *b, unsigned frame)
|
||||
if(!b->sprites[frame])
|
||||
return;
|
||||
if(b->sprites[frame]->surface)
|
||||
SDL_FreeSurface(b->sprites[frame]->surface);
|
||||
SDL_DestroySurface(b->sprites[frame]->surface);
|
||||
b->sprites[frame]->surface = NULL;
|
||||
free(b->sprites[frame]);
|
||||
b->sprites[frame] = NULL;
|
||||
@@ -355,44 +355,51 @@ static int extract_sprite(s_bank_t *bank, unsigned frame,
|
||||
if(!s_new_sprite_b(bank, frame))
|
||||
return -2;
|
||||
|
||||
tmp = SDL_CreateRGBSurface(src->flags,
|
||||
from->w, from->h,
|
||||
src->format->BitsPerPixel,
|
||||
src->format->Rmask,
|
||||
src->format->Gmask,
|
||||
src->format->Bmask,
|
||||
src->format->Amask );
|
||||
const SDL_PixelFormatDetails *src_fmt =
|
||||
SDL_GetPixelFormatDetails(src->format);
|
||||
if(!src_fmt)
|
||||
return -3;
|
||||
|
||||
tmp = SDL_CreateSurface(from->w, from->h, src->format);
|
||||
if(!tmp)
|
||||
return -3;
|
||||
|
||||
/* Copy the pixel data */
|
||||
if(SDL_LockSurface(src) < 0)
|
||||
if(!SDL_LockSurface(src))
|
||||
{
|
||||
log_printf(ELOG, "sprite: extract_sprite() failed to lock surface!\n");
|
||||
SDL_FreeSurface(tmp);
|
||||
SDL_DestroySurface(tmp);
|
||||
return -4;
|
||||
}
|
||||
for(y = 0; y < tmp->h; ++y)
|
||||
{
|
||||
char *s = (char *)src->pixels + src->pitch * (y + from->y) +
|
||||
from->x * src->format->BytesPerPixel;
|
||||
from->x * src_fmt->bytes_per_pixel;
|
||||
char *d = (char *)tmp->pixels + tmp->pitch * y;
|
||||
memcpy(d, s, src->format->BytesPerPixel * tmp->w);
|
||||
memcpy(d, s, src_fmt->bytes_per_pixel * tmp->w);
|
||||
}
|
||||
SDL_UnlockSurface(src);
|
||||
|
||||
/* Copy palette, if any */
|
||||
if(src->format->palette)
|
||||
SDL_SetColors(tmp, src->format->palette->colors, 0,
|
||||
src->format->palette->ncolors);
|
||||
SDL_Palette *src_palette = SDL_GetSurfacePalette(src);
|
||||
if(src_palette)
|
||||
SDL_SetSurfacePalette(tmp, src_palette);
|
||||
|
||||
/* Copy alpha and colorkey */
|
||||
if(src->flags & SDL_SRCALPHA)
|
||||
SDL_SetAlpha(tmp, src->flags & (SDL_SRCALPHA | SDL_RLEACCEL),
|
||||
src->format->alpha);
|
||||
if(src->flags & SDL_SRCCOLORKEY)
|
||||
SDL_SetColorKey(tmp, src->flags & (SDL_SRCCOLORKEY | SDL_RLEACCEL),
|
||||
src->format->colorkey);
|
||||
/* Copy alpha modulation and blend mode */
|
||||
Uint8 src_alpha = SDL_ALPHA_OPAQUE;
|
||||
SDL_GetSurfaceAlphaMod(src, &src_alpha);
|
||||
SDL_SetSurfaceAlphaMod(tmp, src_alpha);
|
||||
SDL_BlendMode src_blend = SDL_BLENDMODE_NONE;
|
||||
SDL_GetSurfaceBlendMode(src, &src_blend);
|
||||
SDL_SetSurfaceBlendMode(tmp, src_blend);
|
||||
|
||||
/* Copy colorkey */
|
||||
if(SDL_SurfaceHasColorKey(src))
|
||||
{
|
||||
Uint32 src_key = 0;
|
||||
SDL_GetSurfaceColorKey(src, &src_key);
|
||||
SDL_SetSurfaceColorKey(tmp, true, src_key);
|
||||
}
|
||||
|
||||
bank->sprites[frame]->surface = tmp;
|
||||
|
||||
@@ -466,21 +473,23 @@ int s_load_image(s_container_t *c, unsigned bank, const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
b = s_new_bank(c, bank, 1, src->clip_rect.w, src->clip_rect.h);
|
||||
SDL_Rect src_clip;
|
||||
SDL_GetSurfaceClipRect(src, &src_clip);
|
||||
b = s_new_bank(c, bank, 1, src_clip.w, src_clip.h);
|
||||
if(!b)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Failed to allocate bank for \"%s\"!\n", name);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(extract_sprite(b, 0, src, &src->clip_rect) < 0)
|
||||
if(extract_sprite(b, 0, src, &src_clip) < 0)
|
||||
{
|
||||
log_printf(ELOG, "sprite: Something went wrong while"
|
||||
" extracting sprite \"%s\".\n", name);
|
||||
return -3;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(src);
|
||||
SDL_DestroySurface(src);
|
||||
__run_plugins(b, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -506,7 +515,7 @@ int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
|
||||
return -1;
|
||||
}
|
||||
|
||||
from = src->clip_rect;
|
||||
SDL_GetSurfaceClipRect(src, &from);
|
||||
if( (from.w != b->w) || (from.h != b->h) )
|
||||
{
|
||||
log_printf(ELOG, "sprite: Warning: Sprite \"%s\" cropped"
|
||||
@@ -522,7 +531,7 @@ int s_load_sprite(s_container_t *c, unsigned bank, unsigned frame,
|
||||
return -3;
|
||||
}
|
||||
|
||||
SDL_FreeSurface(src);
|
||||
SDL_DestroySurface(src);
|
||||
__run_plugins(b, frame, 1);
|
||||
return 0;
|
||||
}
|
||||
@@ -582,7 +591,7 @@ int s_load_bank(s_container_t *c, unsigned bank, unsigned w, unsigned h,
|
||||
}
|
||||
++frame;
|
||||
}
|
||||
SDL_FreeSurface(src);
|
||||
SDL_DestroySurface(src);
|
||||
__run_plugins(b, 0, frames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+18
-21
@@ -50,7 +50,7 @@ window_t::window_t()
|
||||
window_t::~window_t()
|
||||
{
|
||||
if(_offscreen && surface)
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_DestroySurface(surface);
|
||||
if(selected == this)
|
||||
selected = NULL;
|
||||
unlink();
|
||||
@@ -64,7 +64,7 @@ void window_t::init(gfxengine_t *e)
|
||||
ys = engine->ys;
|
||||
if(_offscreen && surface)
|
||||
{
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_DestroySurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
_offscreen = 0;
|
||||
@@ -137,14 +137,10 @@ int window_t::offscreen()
|
||||
return 0; // Already offscreen!
|
||||
visible(0);
|
||||
_offscreen = 1;
|
||||
SDL_Surface *s = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
phys_rect.w, phys_rect.h,
|
||||
32, 0xff000000, 0x00ff0000,
|
||||
0x0000ff00, 0x000000ff);
|
||||
if(!s)
|
||||
return -1;
|
||||
surface = SDL_DisplayFormat(s);
|
||||
SDL_FreeSurface(s);
|
||||
// SDL 3: back buffer is always ARGB8888; offscreen windows use
|
||||
// the same format to allow direct blits without conversion.
|
||||
surface = SDL_CreateSurface(phys_rect.w, phys_rect.h,
|
||||
SDL_PIXELFORMAT_ARGB8888);
|
||||
if(!surface)
|
||||
return -1;
|
||||
return 0;
|
||||
@@ -163,7 +159,7 @@ void window_t::_select()
|
||||
SDL_Rect r = phys_rect;
|
||||
selected = this;
|
||||
if(surface)
|
||||
SDL_SetClipRect(surface, &r);
|
||||
SDL_SetSurfaceClipRect(surface, &r);
|
||||
}
|
||||
|
||||
|
||||
@@ -248,7 +244,7 @@ Uint32 window_t::map_rgb(Uint8 r, Uint8 g, Uint8 b)
|
||||
return 0;
|
||||
|
||||
if(surface)
|
||||
return SDL_MapRGB(surface->format, r, g, b);
|
||||
return SDL_MapSurfaceRGB(surface, r, g, b);
|
||||
else
|
||||
return 0xffffff;
|
||||
}
|
||||
@@ -263,7 +259,7 @@ Uint32 window_t::map_rgb(Uint32 rgb)
|
||||
Uint8 b = rgb & 0xff;
|
||||
|
||||
if(surface)
|
||||
return SDL_MapRGB(surface->format, r, g, b);
|
||||
return SDL_MapSurfaceRGB(surface, r, g, b);
|
||||
else
|
||||
return 0xffffff;
|
||||
}
|
||||
@@ -283,7 +279,7 @@ void window_t::colorkey(Uint32 color)
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetColorKey(surface, SDL_SRCCOLORKEY, color);
|
||||
SDL_SetSurfaceColorKey(surface, true, color);
|
||||
}
|
||||
|
||||
void window_t::colorkey()
|
||||
@@ -294,7 +290,7 @@ void window_t::colorkey()
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetColorKey(surface, 0, 0);
|
||||
SDL_SetSurfaceColorKey(surface, false, 0);
|
||||
}
|
||||
|
||||
void window_t::alpha(float a)
|
||||
@@ -305,7 +301,8 @@ void window_t::alpha(float a)
|
||||
return;
|
||||
if(!_offscreen)
|
||||
return;
|
||||
SDL_SetAlpha(surface, SDL_SRCALPHA, (int)(a * 255.0));
|
||||
SDL_SetSurfaceAlphaMod(surface, (Uint8)(a * 255.0f));
|
||||
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
|
||||
}
|
||||
|
||||
|
||||
@@ -476,13 +473,13 @@ void window_t::clear(SDL_Rect *r)
|
||||
dr.y += phys_rect.y;
|
||||
}
|
||||
if((-1 == bg_bank) && (-1 == bg_frame))
|
||||
SDL_FillRect(surface, &dr, bgcolor);
|
||||
SDL_FillSurfaceRect(surface, &dr, bgcolor);
|
||||
else
|
||||
{
|
||||
s_sprite_t *s = engine->get_sprite(bg_bank, bg_frame);
|
||||
if(!s || !s->surface)
|
||||
{
|
||||
SDL_FillRect(surface, &dr, bgcolor);
|
||||
SDL_FillSurfaceRect(surface, &dr, bgcolor);
|
||||
return;
|
||||
}
|
||||
SDL_BlitSurface(s->surface, &sr, surface, &dr);
|
||||
@@ -507,7 +504,7 @@ void window_t::point(int _x, int _y)
|
||||
r.w = x2 - _x;
|
||||
r.h = y2 - _y;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
SDL_FillSurfaceRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
@@ -527,7 +524,7 @@ void window_t::fillrect(int _x, int _y, int w, int h)
|
||||
r.w = x2 - _x;
|
||||
r.h = y2 - _y;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
SDL_FillSurfaceRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
@@ -556,7 +553,7 @@ void window_t::fillrect_fxp(int _x, int _y, int w, int h)
|
||||
r.w = w;
|
||||
r.h = h;
|
||||
if(surface)
|
||||
SDL_FillRect(surface, &r, fgcolor);
|
||||
SDL_FillSurfaceRect(surface, &r, fgcolor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user