From a104a84700568ee9fb19bb765143b3e41cb87a00 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Wed, 28 Jan 2026 19:39:53 +0100 Subject: [PATCH] Set display texture from a frame Add a function to set a texture from an AVFrame on a sc_display. --- app/src/display.c | 57 ++++++++++++++++++++++++++++++----------------- app/src/display.h | 16 ++++++++----- app/src/screen.c | 9 +------- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/app/src/display.c b/app/src/display.c index 727a6374..3294385d 100644 --- a/app/src/display.c +++ b/app/src/display.c @@ -77,9 +77,10 @@ sc_display_to_sdl_color_space(enum AVColorSpace color_space, } static SDL_Texture * -sc_display_create_texture(struct sc_display *display, - struct sc_size size, enum AVColorSpace color_space, - enum AVColorRange color_range) { +sc_display_create_frame_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; @@ -154,28 +155,40 @@ sc_display_create_texture(struct sc_display *display, } bool -sc_display_prepare_texture(struct sc_display *display, struct sc_size size, - enum AVColorSpace color_space, - enum AVColorRange color_range) { +sc_display_set_texture_from_frame(struct sc_display *display, + const AVFrame *frame) { + + struct sc_size size = {frame->width, frame->height}; assert(size.width && size.height); - if (display->texture) { - SDL_DestroyTexture(display->texture); + if (!display->texture + || display->texture_type != SC_TEXTURE_TYPE_FRAME + || display->texture_size.width != size.width + || display->texture_size.height != size.height) { + // Incompatible texture, recreate it + enum AVColorSpace color_space = frame->colorspace; + enum AVColorRange color_range = frame->color_range; + + if (display->texture) { + SDL_DestroyTexture(display->texture); + } + + display->texture = sc_display_create_frame_texture(display, size, + color_space, + color_range); + if (!display->texture) { + return false; + } + + display->texture_size = size; + display->texture_type = SC_TEXTURE_TYPE_FRAME; + + LOGI("Texture: %" PRIu16 "x%" PRIu16, size.width, size.height); } - display->texture = - sc_display_create_texture(display, size, color_space, color_range); - if (!display->texture) { - return false; - } - - LOGI("Texture: %" PRIu16 "x%" PRIu16, size.width, size.height); - return true; -} - -bool -sc_display_update_texture(struct sc_display *display, const AVFrame *frame) { assert(display->texture); + assert(display->texture_type == SC_TEXTURE_TYPE_FRAME); + bool ok = SDL_UpdateYUVTexture(display->texture, NULL, frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], @@ -210,5 +223,9 @@ sc_display_set_texture_from_surface(struct sc_display *display, return false; } + display->texture_size.width = surface->w; + display->texture_size.height = surface->h; + display->texture_type = SC_TEXTURE_TYPE_ICON; + return true; } diff --git a/app/src/display.h b/app/src/display.h index cda907d3..6fb64d7f 100644 --- a/app/src/display.h +++ b/app/src/display.h @@ -11,9 +11,17 @@ #include "coords.h" #include "opengl.h" +enum sc_texture_type { + SC_TEXTURE_TYPE_FRAME, + SC_TEXTURE_TYPE_ICON, +}; + struct sc_display { SDL_Renderer *renderer; // owned by the caller SDL_Texture *texture; + // Only valid if texture != NULL + struct sc_size texture_size; + enum sc_texture_type texture_type; struct sc_opengl gl; @@ -29,12 +37,8 @@ void sc_display_destroy(struct sc_display *display); bool -sc_display_prepare_texture(struct sc_display *display, struct sc_size size, - enum AVColorSpace color_space, - enum AVColorRange color_range); - -bool -sc_display_update_texture(struct sc_display *display, const AVFrame *frame); +sc_display_set_texture_from_frame(struct sc_display *display, + const AVFrame *frame); bool sc_display_set_texture_from_surface(struct sc_display *display, diff --git a/app/src/screen.c b/app/src/screen.c index c988dbc7..cad968b3 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -704,13 +704,6 @@ sc_screen_apply_frame(struct sc_screen *screen) { || screen->frame_size.width != new_frame_size.width || screen->frame_size.height != new_frame_size.height) { - bool ok = - sc_display_prepare_texture(&screen->display, new_frame_size, - frame->colorspace, frame->color_range); - if (!ok) { - return false; - } - // frame dimension changed screen->frame_size = new_frame_size; @@ -726,7 +719,7 @@ sc_screen_apply_frame(struct sc_screen *screen) { } } - bool ok = sc_display_update_texture(&screen->display, frame); + bool ok = sc_display_set_texture_from_frame(&screen->display, frame); if (!ok) { return false; }