Migrate from SDL2 to SDL3

Refs <https://wiki.libsdl.org/SDL3/README-migration>
This commit is contained in:
Romain Vimont
2025-07-11 09:42:03 +02:00
parent 6e16d0503b
commit 462cd8d615
35 changed files with 674 additions and 573 deletions

View File

@@ -12,8 +12,11 @@ sc_display_init_novideo_icon(struct sc_display *display,
SDL_Surface *icon_novideo) {
assert(icon_novideo);
if (SDL_RenderSetLogicalSize(display->renderer,
icon_novideo->w, icon_novideo->h)) {
bool ok = SDL_SetRenderLogicalPresentation(display->renderer,
icon_novideo->w,
icon_novideo->h,
SDL_LOGICAL_PRESENTATION_LETTERBOX);
if (!ok) {
LOGW("Could not set renderer logical size: %s", SDL_GetError());
// don't fail
}
@@ -31,16 +34,13 @@ sc_display_init_novideo_icon(struct sc_display *display,
bool
sc_display_init(struct sc_display *display, SDL_Window *window,
SDL_Surface *icon_novideo, bool mipmaps) {
display->renderer =
SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
display->renderer = SDL_CreateRenderer(window, NULL);
if (!display->renderer) {
LOGE("Could not create renderer: %s", SDL_GetError());
return false;
}
SDL_RendererInfo renderer_info;
int r = SDL_GetRendererInfo(display->renderer, &renderer_info);
const char *renderer_name = r ? NULL : renderer_info.name;
const char *renderer_name = SDL_GetRendererName(display->renderer);
LOGI("Renderer: %s", renderer_name ? renderer_name : "(unknown)");
display->mipmaps = false;
@@ -56,8 +56,11 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
// Persuade macOS to give us something better than OpenGL 2.1.
// If we create a Core Profile context, we get the best OpenGL version.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
bool ok = SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
if (!ok) {
LOGW("Could not set a GL Core Profile Context");
}
LOGD("Creating OpenGL Core Profile context");
display->gl_context = SDL_GL_CreateContext(window);
@@ -100,7 +103,7 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
bool ok = sc_display_init_novideo_icon(display, icon_novideo);
if (!ok) {
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
SDL_GL_DeleteContext(display->gl_context);
SDL_GL_DestroyContext(display->gl_context);
#endif
SDL_DestroyRenderer(display->renderer);
return false;
@@ -116,7 +119,7 @@ sc_display_destroy(struct sc_display *display) {
av_frame_free(&display->pending.frame);
}
#ifdef SC_DISPLAY_FORCE_OPENGL_CORE_PROFILE
SDL_GL_DeleteContext(display->gl_context);
SDL_GL_DestroyContext(display->gl_context);
#endif
if (display->texture) {
SDL_DestroyTexture(display->texture);
@@ -124,20 +127,25 @@ sc_display_destroy(struct sc_display *display) {
SDL_DestroyRenderer(display->renderer);
}
static SDL_YUV_CONVERSION_MODE
sc_display_to_sdl_color_mode(enum AVColorSpace color_space,
enum AVColorRange color_range) {
static enum SDL_Colorspace
sc_display_to_sdl_color_space(enum AVColorSpace color_space,
enum AVColorRange color_range) {
bool full_range = color_range == AVCOL_RANGE_JPEG;
switch (color_space) {
case AVCOL_SPC_BT709:
return SDL_YUV_CONVERSION_BT709;
return full_range ? SDL_COLORSPACE_BT709_FULL
: SDL_COLORSPACE_BT709_LIMITED;
case AVCOL_SPC_BT470BG:
case AVCOL_SPC_SMPTE170M:
return SDL_YUV_CONVERSION_BT601;
return full_range ? SDL_COLORSPACE_BT601_FULL
: SDL_COLORSPACE_BT601_LIMITED;
case AVCOL_SPC_BT2020_NCL:
case AVCOL_SPC_BT2020_CL:
return full_range ? SDL_COLORSPACE_BT2020_FULL
: SDL_COLORSPACE_BT2020_LIMITED;
default:
if (color_range == AVCOL_RANGE_JPEG) {
return SDL_YUV_CONVERSION_JPEG;
}
return SDL_YUV_CONVERSION_AUTOMATIC;
return SDL_COLORSPACE_JPEG;
}
}
@@ -145,10 +153,36 @@ static SDL_Texture *
sc_display_create_texture(struct sc_display *display,
struct sc_size size, enum AVColorSpace color_space,
enum AVColorRange color_range) {
SDL_PropertiesID props = SDL_CreateProperties();
if (!props) {
return NULL;
}
enum SDL_Colorspace sdl_color_space =
sc_display_to_sdl_color_space(color_space, color_range);
bool ok =
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER,
SDL_PIXELFORMAT_YV12);
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER,
SDL_TEXTUREACCESS_STREAMING);
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER,
size.width);
ok &= SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER,
size.height);
ok &= SDL_SetNumberProperty(props,
SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER,
sdl_color_space);
if (!ok) {
LOGE("Could not set texture properties");
SDL_DestroyProperties(props);
return NULL;
}
SDL_Renderer *renderer = display->renderer;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
size.width, size.height);
SDL_Texture *texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!texture) {
LOGD("Could not create texture: %s", SDL_GetError());
return NULL;
@@ -157,21 +191,38 @@ sc_display_create_texture(struct sc_display *display,
if (display->mipmaps) {
struct sc_opengl *gl = &display->gl;
SDL_GL_BindTexture(texture, NULL, NULL);
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
if (!props) {
LOGE("Could not get texture properties: %s", SDL_GetError());
SDL_DestroyTexture(texture);
return NULL;
}
const char *renderer_name = SDL_GetRendererName(display->renderer);
const char *key = !renderer_name || !strcmp(renderer_name, "opengl")
? SDL_PROP_TEXTURE_OPENGL_TEXTURE_NUMBER
: SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER;
int64_t texture_id = SDL_GetNumberProperty(props, key, 0);
SDL_DestroyProperties(props);
if (!texture_id) {
LOGE("Could not get texture id: %s", SDL_GetError());
SDL_DestroyTexture(texture);
return NULL;
}
assert(!(texture_id & ~0xFFFFFFFF)); // fits in uint32_t
display->texture_id = texture_id;
gl->BindTexture(GL_TEXTURE_2D, display->texture_id);
// Enable trilinear filtering for downscaling
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
gl->TexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1.f);
SDL_GL_UnbindTexture(texture);
gl->BindTexture(GL_TEXTURE_2D, 0);
}
// Configure YUV color range conversion
SDL_YUV_CONVERSION_MODE sdl_color_mode =
sc_display_to_sdl_color_mode(color_space, color_range);
SDL_SetYUVConversionMode(sdl_color_mode);
return texture;
}
@@ -282,19 +333,22 @@ sc_display_prepare_texture(struct sc_display *display, struct sc_size size,
static bool
sc_display_update_texture_internal(struct sc_display *display,
const AVFrame *frame) {
int ret = SDL_UpdateYUVTexture(display->texture, NULL,
bool ok = SDL_UpdateYUVTexture(display->texture, NULL,
frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1],
frame->data[2], frame->linesize[2]);
if (ret) {
if (!ok) {
LOGD("Could not update texture: %s", SDL_GetError());
return false;
}
if (display->mipmaps) {
SDL_GL_BindTexture(display->texture, NULL, NULL);
assert(display->texture_id);
struct sc_opengl *gl = &display->gl;
gl->BindTexture(GL_TEXTURE_2D, display->texture_id);
display->gl.GenerateMipmap(GL_TEXTURE_2D);
SDL_GL_UnbindTexture(display->texture);
gl->BindTexture(GL_TEXTURE_2D, 0);
}
return true;
@@ -332,8 +386,10 @@ sc_display_render(struct sc_display *display, const SDL_Rect *geometry,
SDL_Texture *texture = display->texture;
if (orientation == SC_ORIENTATION_0) {
int ret = SDL_RenderCopy(renderer, texture, NULL, geometry);
if (ret) {
SDL_FRect frect;
SDL_RectToFRect(geometry, &frect);
bool ok = SDL_RenderTexture(renderer, texture, NULL, &frect);
if (!ok) {
LOGE("Could not render texture: %s", SDL_GetError());
return SC_DISPLAY_RESULT_ERROR;
}
@@ -341,24 +397,22 @@ sc_display_render(struct sc_display *display, const SDL_Rect *geometry,
unsigned cw_rotation = sc_orientation_get_rotation(orientation);
double angle = 90 * cw_rotation;
const SDL_Rect *dstrect = NULL;
SDL_Rect rect;
SDL_FRect frect;
if (sc_orientation_is_swap(orientation)) {
rect.x = geometry->x + (geometry->w - geometry->h) / 2;
rect.y = geometry->y + (geometry->h - geometry->w) / 2;
rect.w = geometry->h;
rect.h = geometry->w;
dstrect = &rect;
frect.x = geometry->x + (geometry->w - geometry->h) / 2.f;
frect.y = geometry->y + (geometry->h - geometry->w) / 2.f;
frect.w = geometry->h;
frect.h = geometry->w;
} else {
dstrect = geometry;
SDL_RectToFRect(geometry, &frect);
}
SDL_RendererFlip flip = sc_orientation_is_mirror(orientation)
SDL_FlipMode flip = sc_orientation_is_mirror(orientation)
? SDL_FLIP_HORIZONTAL : 0;
int ret = SDL_RenderCopyEx(renderer, texture, NULL, dstrect, angle,
NULL, flip);
if (ret) {
bool ok = SDL_RenderTextureRotated(renderer, texture, NULL, &frect,
angle, NULL, flip);
if (!ok) {
LOGE("Could not render texture: %s", SDL_GetError());
return SC_DISPLAY_RESULT_ERROR;
}