Set color range during texture creation

This prepares for the migration to SDL3, where the color range can only
be specified at the time of texture creation.
This commit is contained in:
Romain Vimont 2025-07-03 19:04:09 +02:00
commit 0b840dcef1
3 changed files with 40 additions and 36 deletions

View file

@ -94,7 +94,6 @@ sc_display_init(struct sc_display *display, SDL_Window *window,
display->texture = NULL; display->texture = NULL;
display->pending.flags = 0; display->pending.flags = 0;
display->pending.frame = NULL; display->pending.frame = NULL;
display->has_frame = false;
if (icon_novideo) { if (icon_novideo) {
// Without video, set a static scrcpy icon as window content // Without video, set a static scrcpy icon as window content
@ -125,9 +124,15 @@ sc_display_destroy(struct sc_display *display) {
SDL_DestroyRenderer(display->renderer); SDL_DestroyRenderer(display->renderer);
} }
static SDL_YUV_CONVERSION_MODE
sc_display_to_sdl_color_range(enum AVColorRange color_range) {
return color_range == AVCOL_RANGE_JPEG ? SDL_YUV_CONVERSION_JPEG
: SDL_YUV_CONVERSION_AUTOMATIC;
}
static SDL_Texture * static SDL_Texture *
sc_display_create_texture(struct sc_display *display, sc_display_create_texture(struct sc_display *display,
struct sc_size size) { struct sc_size size, enum AVColorRange color_range) {
SDL_Renderer *renderer = display->renderer; SDL_Renderer *renderer = display->renderer;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
@ -150,14 +155,22 @@ sc_display_create_texture(struct sc_display *display,
SDL_GL_UnbindTexture(texture); SDL_GL_UnbindTexture(texture);
} }
// Configure YUV color range conversion
SDL_YUV_CONVERSION_MODE sdl_color_range =
sc_display_to_sdl_color_range(color_range);
SDL_SetYUVConversionMode(sdl_color_range);
return texture; return texture;
} }
static inline void static inline void
sc_display_set_pending_size(struct sc_display *display, struct sc_size size) { sc_display_set_pending_texture(struct sc_display *display,
struct sc_size size,
enum AVColorRange color_range) {
assert(!display->texture); assert(!display->texture);
display->pending.size = size; display->pending.texture.size = size;
display->pending.flags |= SC_DISPLAY_PENDING_FLAG_SIZE; display->pending.texture.color_range = color_range;
display->pending.flags |= SC_DISPLAY_PENDING_FLAG_TEXTURE;
} }
static bool static bool
@ -183,15 +196,17 @@ sc_display_set_pending_frame(struct sc_display *display, const AVFrame *frame) {
static bool static bool
sc_display_apply_pending(struct sc_display *display) { sc_display_apply_pending(struct sc_display *display) {
if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_SIZE) { if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_TEXTURE) {
assert(!display->texture); assert(!display->texture);
display->texture = display->texture =
sc_display_create_texture(display, display->pending.size); sc_display_create_texture(display,
display->pending.texture.size,
display->pending.texture.color_range);
if (!display->texture) { if (!display->texture) {
return false; return false;
} }
display->pending.flags &= ~SC_DISPLAY_PENDING_FLAG_SIZE; display->pending.flags &= ~SC_DISPLAY_PENDING_FLAG_TEXTURE;
} }
if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_FRAME) { if (display->pending.flags & SC_DISPLAY_PENDING_FLAG_FRAME) {
@ -209,15 +224,16 @@ sc_display_apply_pending(struct sc_display *display) {
} }
static bool static bool
sc_display_set_texture_size_internal(struct sc_display *display, sc_display_prepare_texture_internal(struct sc_display *display,
struct sc_size size) { struct sc_size size,
enum AVColorRange color_range) {
assert(size.width && size.height); assert(size.width && size.height);
if (display->texture) { if (display->texture) {
SDL_DestroyTexture(display->texture); SDL_DestroyTexture(display->texture);
} }
display->texture = sc_display_create_texture(display, size); display->texture = sc_display_create_texture(display, size, color_range);
if (!display->texture) { if (!display->texture) {
return false; return false;
} }
@ -227,10 +243,11 @@ sc_display_set_texture_size_internal(struct sc_display *display,
} }
enum sc_display_result enum sc_display_result
sc_display_set_texture_size(struct sc_display *display, struct sc_size size) { sc_display_prepare_texture(struct sc_display *display, struct sc_size size,
bool ok = sc_display_set_texture_size_internal(display, size); enum AVColorRange color_range) {
bool ok = sc_display_prepare_texture_internal(display, size, color_range);
if (!ok) { if (!ok) {
sc_display_set_pending_size(display, size); sc_display_set_pending_texture(display, size, color_range);
return SC_DISPLAY_RESULT_PENDING; return SC_DISPLAY_RESULT_PENDING;
} }
@ -238,25 +255,9 @@ sc_display_set_texture_size(struct sc_display *display, struct sc_size size) {
return SC_DISPLAY_RESULT_OK; return SC_DISPLAY_RESULT_OK;
} }
static SDL_YUV_CONVERSION_MODE
sc_display_to_sdl_color_range(enum AVColorRange color_range) {
return color_range == AVCOL_RANGE_JPEG ? SDL_YUV_CONVERSION_JPEG
: SDL_YUV_CONVERSION_AUTOMATIC;
}
static bool static bool
sc_display_update_texture_internal(struct sc_display *display, sc_display_update_texture_internal(struct sc_display *display,
const AVFrame *frame) { const AVFrame *frame) {
if (!display->has_frame) {
// First frame
display->has_frame = true;
// Configure YUV color range conversion
SDL_YUV_CONVERSION_MODE sdl_color_range =
sc_display_to_sdl_color_range(frame->color_range);
SDL_SetYUVConversionMode(sdl_color_range);
}
int ret = SDL_UpdateYUVTexture(display->texture, NULL, int ret = SDL_UpdateYUVTexture(display->texture, NULL,
frame->data[0], frame->linesize[0], frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1], frame->data[1], frame->linesize[1],

View file

@ -28,14 +28,15 @@ struct sc_display {
bool mipmaps; bool mipmaps;
struct { struct {
#define SC_DISPLAY_PENDING_FLAG_SIZE 1 #define SC_DISPLAY_PENDING_FLAG_TEXTURE 1
#define SC_DISPLAY_PENDING_FLAG_FRAME 2 #define SC_DISPLAY_PENDING_FLAG_FRAME 2
int8_t flags; int8_t flags;
struct sc_size size; struct {
struct sc_size size;
enum AVColorRange color_range;
} texture;
AVFrame *frame; AVFrame *frame;
} pending; } pending;
bool has_frame;
}; };
enum sc_display_result { enum sc_display_result {
@ -52,7 +53,8 @@ void
sc_display_destroy(struct sc_display *display); sc_display_destroy(struct sc_display *display);
enum sc_display_result enum sc_display_result
sc_display_set_texture_size(struct sc_display *display, struct sc_size size); sc_display_prepare_texture(struct sc_display *display, struct sc_size size,
enum AVColorRange color_range);
enum sc_display_result enum sc_display_result
sc_display_update_texture(struct sc_display *display, const AVFrame *frame); sc_display_update_texture(struct sc_display *display, const AVFrame *frame);

View file

@ -619,7 +619,8 @@ sc_screen_apply_frame(struct sc_screen *screen) {
} }
enum sc_display_result res = enum sc_display_result res =
sc_display_set_texture_size(&screen->display, screen->frame_size); sc_display_prepare_texture(&screen->display, screen->frame_size,
frame->color_range);
if (res == SC_DISPLAY_RESULT_ERROR) { if (res == SC_DISPLAY_RESULT_ERROR) {
return false; return false;
} }