diff --git a/app/src/cli.c b/app/src/cli.c index d9ba6e30..c20d5ba3 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -643,6 +643,7 @@ guess_record_format(const char *filename) { static bool parse_scale_filter(const char *optarg, enum sc_scale_filter *filter) { + // TODO store in a map and loop over the entries instead if (!strcmp(optarg, "none")) { *filter = SC_SCALE_FILTER_NONE; return true; @@ -651,8 +652,49 @@ parse_scale_filter(const char *optarg, enum sc_scale_filter *filter) { *filter = SC_SCALE_FILTER_TRILINEAR; return true; } + if (!strcmp(optarg, "bilinear")) { + *filter = SC_SCALE_FILTER_BILINEAR; + return true; + } + if (!strcmp(optarg, "bicubic")) { + *filter = SC_SCALE_FILTER_BICUBIC; + return true; + } + if (!strcmp(optarg, "x")) { + *filter = SC_SCALE_FILTER_X; + return true; + } + if (!strcmp(optarg, "point")) { + *filter = SC_SCALE_FILTER_POINT; + return true; + } + if (!strcmp(optarg, "area")) { + *filter = SC_SCALE_FILTER_AREA; + return true; + } + if (!strcmp(optarg, "bicublin")) { + *filter = SC_SCALE_FILTER_BICUBLIN; + return true; + } + if (!strcmp(optarg, "gauss")) { + *filter = SC_SCALE_FILTER_GAUSS; + return true; + } + if (!strcmp(optarg, "sinc")) { + *filter = SC_SCALE_FILTER_SINC; + return true; + } + if (!strcmp(optarg, "lanczos")) { + *filter = SC_SCALE_FILTER_LANCZOS; + return true; + } + if (!strcmp(optarg, "spline")) { + *filter = SC_SCALE_FILTER_SPLINE; + return true; + } + LOGE("Unsupported scale filter: %s " - "(expected \"none\" or \"trilinear\")", optarg); + "(expected one of [TODO])", optarg); return false; } diff --git a/app/src/screen.c b/app/src/screen.c index 3c9da023..3fa69131 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -213,7 +213,7 @@ create_texture(struct screen *screen) { return NULL; } - if (screen->mipmaps) { + if (screen->scale_filter == SC_SCALE_FILTER_TRILINEAR) { struct sc_opengl *gl = &screen->gl; SDL_GL_BindTexture(texture, NULL, NULL); @@ -229,6 +229,12 @@ create_texture(struct screen *screen) { return texture; } +static inline bool +is_swscale(enum sc_scale_filter scale_filter) { + return scale_filter != SC_SCALE_FILTER_NONE + && scale_filter != SC_SCALE_FILTER_TRILINEAR; +} + bool screen_init_rendering(struct screen *screen, const char *window_title, struct size frame_size, bool always_on_top, @@ -301,10 +307,10 @@ screen_init_rendering(struct screen *screen, const char *window_title, 2, 0 /* OpenGL ES 2.0+ */); if (supports_mipmaps) { LOGI("Trilinear filtering enabled"); - screen->mipmaps = true; } else { LOGW("Trilinear filtering disabled " "(OpenGL 3.0+ or ES 2.0+ required)"); + scale_filter = SC_SCALE_FILTER_NONE; } } else { LOGI("Trilinear filtering disabled"); @@ -313,6 +319,29 @@ screen_init_rendering(struct screen *screen, const char *window_title, LOGD("Trilinear filtering disabled (not an OpenGL renderer)"); } + screen->use_swscale = is_swscale(scale_filter); + if (screen->use_swscale) { + bool ok = sc_resizer_init(&screen->resizer, screen->vb, + &screen->resizer_vb, scale_filter, + window_size); + if (!ok) { + LOGE("Could not create resizer"); + SDL_DestroyRenderer(screen->renderer); + SDL_DestroyWindow(screen->window); + return false; + } + + ok = sc_resizer_start(&screen->resizer); + if (!ok) { + LOGE("Could not start resizer"); + sc_resizer_destroy(&screen->resizer); + SDL_DestroyRenderer(screen->renderer); + SDL_DestroyWindow(screen->window); + } + } + + screen->scale_filter = scale_filter; + SDL_Surface *icon = read_xpm(icon_xpm); if (icon) { SDL_SetWindowIcon(screen->window, icon); @@ -348,6 +377,11 @@ screen_show_window(struct screen *screen) { void screen_destroy(struct screen *screen) { + if (screen->use_swscale) { + sc_resizer_stop(&screen->resizer); + sc_resizer_join(&screen->resizer); + sc_resizer_destroy(&screen->resizer); + } if (screen->texture) { SDL_DestroyTexture(screen->texture); } @@ -448,7 +482,7 @@ update_texture(struct screen *screen, const AVFrame *frame) { frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]); - if (screen->mipmaps) { + if (screen->scale_filter == SC_SCALE_FILTER_TRILINEAR) { SDL_GL_BindTexture(screen->texture, NULL, NULL); screen->gl.GenerateMipmap(GL_TEXTURE_2D); SDL_GL_UnbindTexture(screen->texture); diff --git a/app/src/screen.h b/app/src/screen.h index 53a62faf..e364635a 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -9,7 +9,9 @@ #include "coords.h" #include "opengl.h" +#include "resizer.h" #include "scrcpy.h" +#include "video_buffer.h" struct video_buffer; @@ -37,6 +39,13 @@ struct screen { bool fullscreen; bool maximized; bool mipmaps; + + enum sc_scale_filter scale_filter; + bool use_swscale; + + // For swscale resizing + struct video_buffer resizer_vb; + struct sc_resizer resizer; }; // initialize default values