From f6570a7a41c007a5ba82d0d23f3a3a79015d67a2 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Fri, 5 Feb 2021 15:44:31 +0100 Subject: [PATCH] scale_filter --- app/scrcpy.1 | 7 +++++++ app/src/cli.c | 36 ++++++++++++++++++++++++++++++------ app/src/frame_texture.c | 13 +++++++------ app/src/frame_texture.h | 6 ++++-- app/src/scrcpy.c | 2 +- app/src/scrcpy.h | 9 +++++++-- app/src/screen.c | 7 +++---- app/src/screen.h | 3 ++- 8 files changed, 61 insertions(+), 22 deletions(-) diff --git a/app/scrcpy.1 b/app/scrcpy.1 index 92b8e1e3..7ebb3430 100644 --- a/app/scrcpy.1 +++ b/app/scrcpy.1 @@ -167,6 +167,13 @@ Set the initial display rotation. Possibles values are 0, 1, 2 and 3. Each incre .BI "\-s, \-\-serial " number The device serial number. Mandatory only if several devices are connected to adb. +.TP +.BI "\-\-scale\-filter filter +Supported filters are "none" and "trilinear". + +Trilinear filtering is only available if the renderer is OpenGL 3.0+ or OpenGL +ES 2.0+. + .TP .BI "\-\-shortcut\-mod " key[+...]][,...] Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lsuper" and "rsuper". diff --git a/app/src/cli.c b/app/src/cli.c index fbdef07f..d9ba6e30 100644 --- a/app/src/cli.c +++ b/app/src/cli.c @@ -103,11 +103,6 @@ scrcpy_print_usage(const char *arg0) { " --no-key-repeat\n" " Do not forward repeated key events when a key is held down.\n" "\n" - " --no-mipmaps\n" - " If the renderer is OpenGL 3.0+ or OpenGL ES 2.0+, then\n" - " mipmaps are automatically generated to improve downscaling\n" - " quality. This option disables the generation of mipmaps.\n" - "\n" " -p, --port port[:port]\n" " Set the TCP port (range) used by the client to listen.\n" " Default is %d:%d.\n" @@ -154,6 +149,11 @@ scrcpy_print_usage(const char *arg0) { " The device serial number. Mandatory only if several devices\n" " are connected to adb.\n" "\n" + " --scale-filter filter\n" + " Supported filters are \"none\" and \"trilinear\".\n" + " Trilinear filtering is only available if the renderer is\n" + " OpenGL 3.0+ or OpenGL ES 2.0+.\n" + "\n" " --shortcut-mod key[+...]][,...]\n" " Specify the modifiers to use for scrcpy shortcuts.\n" " Possible keys are \"lctrl\", \"rctrl\", \"lalt\", \"ralt\",\n" @@ -641,6 +641,21 @@ guess_record_format(const char *filename) { return 0; } +static bool +parse_scale_filter(const char *optarg, enum sc_scale_filter *filter) { + if (!strcmp(optarg, "none")) { + *filter = SC_SCALE_FILTER_NONE; + return true; + } + if (!strcmp(optarg, "trilinear")) { + *filter = SC_SCALE_FILTER_TRILINEAR; + return true; + } + LOGE("Unsupported scale filter: %s " + "(expected \"none\" or \"trilinear\")", optarg); + return false; +} + #define OPT_RENDER_EXPIRED_FRAMES 1000 #define OPT_WINDOW_TITLE 1001 #define OPT_PUSH_TARGET 1002 @@ -667,6 +682,7 @@ guess_record_format(const char *filename) { #define OPT_FORWARD_ALL_CLICKS 1023 #define OPT_LEGACY_PASTE 1024 #define OPT_ENCODER_NAME 1025 +#define OPT_SCALE_FILTER 1026 bool scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { @@ -703,6 +719,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { {"render-expired-frames", no_argument, NULL, OPT_RENDER_EXPIRED_FRAMES}, {"rotation", required_argument, NULL, OPT_ROTATION}, + {"scale-filter", required_argument, NULL, OPT_SCALE_FILTER}, {"serial", required_argument, NULL, 's'}, {"shortcut-mod", required_argument, NULL, OPT_SHORTCUT_MOD}, {"show-touches", no_argument, NULL, 't'}, @@ -857,7 +874,9 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { opts->render_driver = optarg; break; case OPT_NO_MIPMAPS: - opts->mipmaps = false; + LOGW("Deprecated option --no-mipmaps. " + "Use --scale-filter=none instead."); + opts->scale_filter = SC_SCALE_FILTER_NONE; break; case OPT_NO_KEY_REPEAT: opts->forward_key_repeat = false; @@ -885,6 +904,11 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) { case OPT_LEGACY_PASTE: opts->legacy_paste = true; break; + case OPT_SCALE_FILTER: + if (!parse_scale_filter(optarg, &opts->scale_filter)) { + return false; + } + break; default: // getopt prints the error message on stderr return false; diff --git a/app/src/frame_texture.c b/app/src/frame_texture.c index d7edde70..7baf89e2 100644 --- a/app/src/frame_texture.c +++ b/app/src/frame_texture.c @@ -12,7 +12,7 @@ create_texture(struct sc_frame_texture *ftex, struct size size) { return NULL; } - if (ftex->mipmaps) { + if (ftex->scale_filter == SC_SCALE_FILTER_TRILINEAR) { struct sc_opengl *gl = &ftex->gl; SDL_GL_BindTexture(texture, NULL, NULL); @@ -30,13 +30,14 @@ create_texture(struct sc_frame_texture *ftex, struct size size) { bool sc_frame_texture_init(struct sc_frame_texture *ftex, SDL_Renderer *renderer, - bool mipmaps, struct size initial_size) { + enum sc_scale_filter scale_filter, + struct size initial_size) { SDL_RendererInfo renderer_info; int r = SDL_GetRendererInfo(renderer, &renderer_info); const char *renderer_name = r ? NULL : renderer_info.name; LOGI("Renderer: %s", renderer_name ? renderer_name : "(unknown)"); - ftex->mipmaps = false; + ftex->scale_filter = scale_filter; // starts with "opengl" bool use_opengl = renderer_name && !strncmp(renderer_name, "opengl", 6); @@ -46,16 +47,16 @@ sc_frame_texture_init(struct sc_frame_texture *ftex, SDL_Renderer *renderer, LOGI("OpenGL version: %s", gl->version); - if (mipmaps) { + if (scale_filter == SC_SCALE_FILTER_TRILINEAR) { bool supports_mipmaps = sc_opengl_version_at_least(gl, 3, 0, /* OpenGL 3.0+ */ 2, 0 /* OpenGL ES 2.0+ */); if (supports_mipmaps) { LOGI("Trilinear filtering enabled"); - ftex->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"); @@ -110,7 +111,7 @@ sc_frame_texture_update(struct sc_frame_texture *ftex, const AVFrame *frame) { frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]); - if (ftex->mipmaps) { + if (ftex->scale_filter == SC_SCALE_FILTER_TRILINEAR) { SDL_GL_BindTexture(ftex->texture, NULL, NULL); ftex->gl.GenerateMipmap(GL_TEXTURE_2D); SDL_GL_UnbindTexture(ftex->texture); diff --git a/app/src/frame_texture.h b/app/src/frame_texture.h index 626a600b..773621be 100644 --- a/app/src/frame_texture.h +++ b/app/src/frame_texture.h @@ -9,11 +9,12 @@ #include "coords.h" #include "opengl.h" +#include "scrcpy.h" struct sc_frame_texture { SDL_Renderer *renderer; // owned by struct screen - bool mipmaps; + enum sc_scale_filter scale_filter; struct sc_opengl gl; SDL_Texture *texture; @@ -22,7 +23,8 @@ struct sc_frame_texture { bool sc_frame_texture_init(struct sc_frame_texture *ftex, SDL_Renderer *renderer, - bool mipmaps, struct size initial_size); + enum sc_scale_filter scale_filter, + struct size initial_size); void sc_frame_texture_destroy(struct sc_frame_texture *ftex); diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index 505b5eaf..82b65018 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -434,7 +434,7 @@ scrcpy(const struct scrcpy_options *options) { options->window_y, options->window_width, options->window_height, options->window_borderless, - options->rotation, options->mipmaps)) { + options->rotation, options->scale_filter)) { goto end; } diff --git a/app/src/scrcpy.h b/app/src/scrcpy.h index 2253cc28..a89fa59c 100644 --- a/app/src/scrcpy.h +++ b/app/src/scrcpy.h @@ -41,6 +41,11 @@ struct sc_port_range { uint16_t last; }; +enum sc_scale_filter { + SC_SCALE_FILTER_NONE, + SC_SCALE_FILTER_TRILINEAR, // mipmaps +}; + #define SC_WINDOW_POSITION_UNDEFINED (-0x8000) struct scrcpy_options { @@ -56,6 +61,7 @@ struct scrcpy_options { enum sc_record_format record_format; struct sc_port_range port_range; struct sc_shortcut_mods shortcut_mods; + enum sc_scale_filter scale_filter; uint16_t max_size; uint32_t bit_rate; uint16_t max_fps; @@ -75,7 +81,6 @@ struct scrcpy_options { bool render_expired_frames; bool prefer_text; bool window_borderless; - bool mipmaps; bool stay_awake; bool force_adb_forward; bool disable_screensaver; @@ -103,6 +108,7 @@ struct scrcpy_options { .data = {SC_MOD_LALT, SC_MOD_LSUPER}, \ .count = 2, \ }, \ + .scale_filter = SC_SCALE_FILTER_TRILINEAR, \ .max_size = DEFAULT_MAX_SIZE, \ .bit_rate = DEFAULT_BIT_RATE, \ .max_fps = 0, \ @@ -122,7 +128,6 @@ struct scrcpy_options { .render_expired_frames = false, \ .prefer_text = false, \ .window_borderless = false, \ - .mipmaps = true, \ .stay_awake = false, \ .force_adb_forward = false, \ .disable_screensaver = false, \ diff --git a/app/src/screen.c b/app/src/screen.c index 0d3f8038..90b0c196 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -5,7 +5,6 @@ #include #include "icon.xpm" -#include "scrcpy.h" #include "tiny_xpm.h" #include "video_buffer.h" #include "util/log.h" @@ -200,7 +199,7 @@ screen_init_rendering(struct screen *screen, const char *window_title, struct size frame_size, bool always_on_top, int16_t window_x, int16_t window_y, uint16_t window_width, uint16_t window_height, bool window_borderless, - uint8_t rotation, bool mipmaps) { + uint8_t rotation, enum sc_scale_filter scale_filter) { screen->frame_size = frame_size; screen->rotation = rotation; if (rotation) { @@ -247,8 +246,8 @@ screen_init_rendering(struct screen *screen, const char *window_title, return false; } - bool ok = sc_frame_texture_init(&screen->ftex, screen->renderer, mipmaps, - frame_size); + bool ok = sc_frame_texture_init(&screen->ftex, screen->renderer, + scale_filter, frame_size); if (!ok) { LOGC("Could not init frame texture"); SDL_DestroyRenderer(screen->renderer); diff --git a/app/src/screen.h b/app/src/screen.h index 9a3a0d25..417ea0e3 100644 --- a/app/src/screen.h +++ b/app/src/screen.h @@ -10,6 +10,7 @@ #include "coords.h" #include "frame_texture.h" #include "opengl.h" +#include "scrcpy.h" struct video_buffer; @@ -77,7 +78,7 @@ screen_init_rendering(struct screen *screen, const char *window_title, struct size frame_size, bool always_on_top, int16_t window_x, int16_t window_y, uint16_t window_width, uint16_t window_height, bool window_borderless, - uint8_t rotation, bool mipmaps); + uint8_t rotation, enum sc_scale_filter scale_filter); // show the window void