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.

PR #6216 <https://github.com/Genymobile/scrcpy/pull/6216>
This commit is contained in:
Romain Vimont
2025-07-03 19:04:09 +02:00
parent 3571fe62ed
commit ed62ca124c
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->pending.flags = 0;
display->pending.frame = NULL;
display->has_frame = false;
if (icon_novideo) {
// 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);
}
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 *
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_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING,
@@ -150,14 +155,22 @@ sc_display_create_texture(struct sc_display *display,
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;
}
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);
display->pending.size = size;
display->pending.flags |= SC_DISPLAY_PENDING_FLAG_SIZE;
display->pending.texture.size = size;
display->pending.texture.color_range = color_range;
display->pending.flags |= SC_DISPLAY_PENDING_FLAG_TEXTURE;
}
static bool
@@ -189,15 +202,17 @@ sc_display_update_texture_internal(struct sc_display *display,
static bool
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);
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) {
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) {
@@ -216,15 +231,16 @@ sc_display_apply_pending(struct sc_display *display) {
}
static bool
sc_display_set_texture_size_internal(struct sc_display *display,
struct sc_size size) {
sc_display_prepare_texture_internal(struct sc_display *display,
struct sc_size size,
enum AVColorRange color_range) {
assert(size.width && size.height);
if (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) {
return false;
}
@@ -234,10 +250,11 @@ sc_display_set_texture_size_internal(struct sc_display *display,
}
enum sc_display_result
sc_display_set_texture_size(struct sc_display *display, struct sc_size size) {
bool ok = sc_display_set_texture_size_internal(display, size);
sc_display_prepare_texture(struct sc_display *display, struct sc_size size,
enum AVColorRange color_range) {
bool ok = sc_display_prepare_texture_internal(display, size, color_range);
if (!ok) {
sc_display_set_pending_size(display, size);
sc_display_set_pending_texture(display, size, color_range);
return SC_DISPLAY_RESULT_PENDING;
}
@@ -245,25 +262,9 @@ sc_display_set_texture_size(struct sc_display *display, struct sc_size size) {
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
sc_display_update_texture_internal(struct sc_display *display,
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,
frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1],

View File

@@ -28,14 +28,15 @@ struct sc_display {
bool mipmaps;
struct {
#define SC_DISPLAY_PENDING_FLAG_SIZE 1
#define SC_DISPLAY_PENDING_FLAG_TEXTURE 1
#define SC_DISPLAY_PENDING_FLAG_FRAME 2
int8_t flags;
struct sc_size size;
struct {
struct sc_size size;
enum AVColorRange color_range;
} texture;
AVFrame *frame;
} pending;
bool has_frame;
};
enum sc_display_result {
@@ -52,7 +53,8 @@ void
sc_display_destroy(struct sc_display *display);
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
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 =
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) {
return false;
}