mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-02 22:29:25 +00:00
scale_filter
This commit is contained in:
parent
87e3ad7756
commit
f6570a7a41
8 changed files with 61 additions and 22 deletions
|
@ -167,6 +167,13 @@ Set the initial display rotation. Possibles values are 0, 1, 2 and 3. Each incre
|
||||||
.BI "\-s, \-\-serial " number
|
.BI "\-s, \-\-serial " number
|
||||||
The device serial number. Mandatory only if several devices are connected to adb.
|
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
|
.TP
|
||||||
.BI "\-\-shortcut\-mod " key[+...]][,...]
|
.BI "\-\-shortcut\-mod " key[+...]][,...]
|
||||||
Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lsuper" and "rsuper".
|
Specify the modifiers to use for scrcpy shortcuts. Possible keys are "lctrl", "rctrl", "lalt", "ralt", "lsuper" and "rsuper".
|
||||||
|
|
|
@ -103,11 +103,6 @@ scrcpy_print_usage(const char *arg0) {
|
||||||
" --no-key-repeat\n"
|
" --no-key-repeat\n"
|
||||||
" Do not forward repeated key events when a key is held down.\n"
|
" Do not forward repeated key events when a key is held down.\n"
|
||||||
"\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"
|
" -p, --port port[:port]\n"
|
||||||
" Set the TCP port (range) used by the client to listen.\n"
|
" Set the TCP port (range) used by the client to listen.\n"
|
||||||
" Default is %d:%d.\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"
|
" The device serial number. Mandatory only if several devices\n"
|
||||||
" are connected to adb.\n"
|
" are connected to adb.\n"
|
||||||
"\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"
|
" --shortcut-mod key[+...]][,...]\n"
|
||||||
" Specify the modifiers to use for scrcpy shortcuts.\n"
|
" Specify the modifiers to use for scrcpy shortcuts.\n"
|
||||||
" Possible keys are \"lctrl\", \"rctrl\", \"lalt\", \"ralt\",\n"
|
" Possible keys are \"lctrl\", \"rctrl\", \"lalt\", \"ralt\",\n"
|
||||||
|
@ -641,6 +641,21 @@ guess_record_format(const char *filename) {
|
||||||
return 0;
|
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_RENDER_EXPIRED_FRAMES 1000
|
||||||
#define OPT_WINDOW_TITLE 1001
|
#define OPT_WINDOW_TITLE 1001
|
||||||
#define OPT_PUSH_TARGET 1002
|
#define OPT_PUSH_TARGET 1002
|
||||||
|
@ -667,6 +682,7 @@ guess_record_format(const char *filename) {
|
||||||
#define OPT_FORWARD_ALL_CLICKS 1023
|
#define OPT_FORWARD_ALL_CLICKS 1023
|
||||||
#define OPT_LEGACY_PASTE 1024
|
#define OPT_LEGACY_PASTE 1024
|
||||||
#define OPT_ENCODER_NAME 1025
|
#define OPT_ENCODER_NAME 1025
|
||||||
|
#define OPT_SCALE_FILTER 1026
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
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,
|
{"render-expired-frames", no_argument, NULL,
|
||||||
OPT_RENDER_EXPIRED_FRAMES},
|
OPT_RENDER_EXPIRED_FRAMES},
|
||||||
{"rotation", required_argument, NULL, OPT_ROTATION},
|
{"rotation", required_argument, NULL, OPT_ROTATION},
|
||||||
|
{"scale-filter", required_argument, NULL, OPT_SCALE_FILTER},
|
||||||
{"serial", required_argument, NULL, 's'},
|
{"serial", required_argument, NULL, 's'},
|
||||||
{"shortcut-mod", required_argument, NULL, OPT_SHORTCUT_MOD},
|
{"shortcut-mod", required_argument, NULL, OPT_SHORTCUT_MOD},
|
||||||
{"show-touches", no_argument, NULL, 't'},
|
{"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;
|
opts->render_driver = optarg;
|
||||||
break;
|
break;
|
||||||
case OPT_NO_MIPMAPS:
|
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;
|
break;
|
||||||
case OPT_NO_KEY_REPEAT:
|
case OPT_NO_KEY_REPEAT:
|
||||||
opts->forward_key_repeat = false;
|
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:
|
case OPT_LEGACY_PASTE:
|
||||||
opts->legacy_paste = true;
|
opts->legacy_paste = true;
|
||||||
break;
|
break;
|
||||||
|
case OPT_SCALE_FILTER:
|
||||||
|
if (!parse_scale_filter(optarg, &opts->scale_filter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -12,7 +12,7 @@ create_texture(struct sc_frame_texture *ftex, struct size size) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ftex->mipmaps) {
|
if (ftex->scale_filter == SC_SCALE_FILTER_TRILINEAR) {
|
||||||
struct sc_opengl *gl = &ftex->gl;
|
struct sc_opengl *gl = &ftex->gl;
|
||||||
|
|
||||||
SDL_GL_BindTexture(texture, NULL, NULL);
|
SDL_GL_BindTexture(texture, NULL, NULL);
|
||||||
|
@ -30,13 +30,14 @@ create_texture(struct sc_frame_texture *ftex, struct size size) {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sc_frame_texture_init(struct sc_frame_texture *ftex, SDL_Renderer *renderer,
|
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;
|
SDL_RendererInfo renderer_info;
|
||||||
int r = SDL_GetRendererInfo(renderer, &renderer_info);
|
int r = SDL_GetRendererInfo(renderer, &renderer_info);
|
||||||
const char *renderer_name = r ? NULL : renderer_info.name;
|
const char *renderer_name = r ? NULL : renderer_info.name;
|
||||||
LOGI("Renderer: %s", renderer_name ? renderer_name : "(unknown)");
|
LOGI("Renderer: %s", renderer_name ? renderer_name : "(unknown)");
|
||||||
|
|
||||||
ftex->mipmaps = false;
|
ftex->scale_filter = scale_filter;
|
||||||
|
|
||||||
// starts with "opengl"
|
// starts with "opengl"
|
||||||
bool use_opengl = renderer_name && !strncmp(renderer_name, "opengl", 6);
|
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);
|
LOGI("OpenGL version: %s", gl->version);
|
||||||
|
|
||||||
if (mipmaps) {
|
if (scale_filter == SC_SCALE_FILTER_TRILINEAR) {
|
||||||
bool supports_mipmaps =
|
bool supports_mipmaps =
|
||||||
sc_opengl_version_at_least(gl, 3, 0, /* OpenGL 3.0+ */
|
sc_opengl_version_at_least(gl, 3, 0, /* OpenGL 3.0+ */
|
||||||
2, 0 /* OpenGL ES 2.0+ */);
|
2, 0 /* OpenGL ES 2.0+ */);
|
||||||
if (supports_mipmaps) {
|
if (supports_mipmaps) {
|
||||||
LOGI("Trilinear filtering enabled");
|
LOGI("Trilinear filtering enabled");
|
||||||
ftex->mipmaps = true;
|
|
||||||
} else {
|
} else {
|
||||||
LOGW("Trilinear filtering disabled "
|
LOGW("Trilinear filtering disabled "
|
||||||
"(OpenGL 3.0+ or ES 2.0+ required)");
|
"(OpenGL 3.0+ or ES 2.0+ required)");
|
||||||
|
scale_filter = SC_SCALE_FILTER_NONE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGI("Trilinear filtering disabled");
|
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[1], frame->linesize[1],
|
||||||
frame->data[2], frame->linesize[2]);
|
frame->data[2], frame->linesize[2]);
|
||||||
|
|
||||||
if (ftex->mipmaps) {
|
if (ftex->scale_filter == SC_SCALE_FILTER_TRILINEAR) {
|
||||||
SDL_GL_BindTexture(ftex->texture, NULL, NULL);
|
SDL_GL_BindTexture(ftex->texture, NULL, NULL);
|
||||||
ftex->gl.GenerateMipmap(GL_TEXTURE_2D);
|
ftex->gl.GenerateMipmap(GL_TEXTURE_2D);
|
||||||
SDL_GL_UnbindTexture(ftex->texture);
|
SDL_GL_UnbindTexture(ftex->texture);
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
|
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
#include "scrcpy.h"
|
||||||
|
|
||||||
struct sc_frame_texture {
|
struct sc_frame_texture {
|
||||||
SDL_Renderer *renderer; // owned by struct screen
|
SDL_Renderer *renderer; // owned by struct screen
|
||||||
|
|
||||||
bool mipmaps;
|
enum sc_scale_filter scale_filter;
|
||||||
struct sc_opengl gl;
|
struct sc_opengl gl;
|
||||||
|
|
||||||
SDL_Texture *texture;
|
SDL_Texture *texture;
|
||||||
|
@ -22,7 +23,8 @@ struct sc_frame_texture {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sc_frame_texture_init(struct sc_frame_texture *ftex, SDL_Renderer *renderer,
|
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
|
void
|
||||||
sc_frame_texture_destroy(struct sc_frame_texture *ftex);
|
sc_frame_texture_destroy(struct sc_frame_texture *ftex);
|
||||||
|
|
|
@ -434,7 +434,7 @@ scrcpy(const struct scrcpy_options *options) {
|
||||||
options->window_y, options->window_width,
|
options->window_y, options->window_width,
|
||||||
options->window_height,
|
options->window_height,
|
||||||
options->window_borderless,
|
options->window_borderless,
|
||||||
options->rotation, options->mipmaps)) {
|
options->rotation, options->scale_filter)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,11 @@ struct sc_port_range {
|
||||||
uint16_t last;
|
uint16_t last;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sc_scale_filter {
|
||||||
|
SC_SCALE_FILTER_NONE,
|
||||||
|
SC_SCALE_FILTER_TRILINEAR, // mipmaps
|
||||||
|
};
|
||||||
|
|
||||||
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)
|
#define SC_WINDOW_POSITION_UNDEFINED (-0x8000)
|
||||||
|
|
||||||
struct scrcpy_options {
|
struct scrcpy_options {
|
||||||
|
@ -56,6 +61,7 @@ struct scrcpy_options {
|
||||||
enum sc_record_format record_format;
|
enum sc_record_format record_format;
|
||||||
struct sc_port_range port_range;
|
struct sc_port_range port_range;
|
||||||
struct sc_shortcut_mods shortcut_mods;
|
struct sc_shortcut_mods shortcut_mods;
|
||||||
|
enum sc_scale_filter scale_filter;
|
||||||
uint16_t max_size;
|
uint16_t max_size;
|
||||||
uint32_t bit_rate;
|
uint32_t bit_rate;
|
||||||
uint16_t max_fps;
|
uint16_t max_fps;
|
||||||
|
@ -75,7 +81,6 @@ struct scrcpy_options {
|
||||||
bool render_expired_frames;
|
bool render_expired_frames;
|
||||||
bool prefer_text;
|
bool prefer_text;
|
||||||
bool window_borderless;
|
bool window_borderless;
|
||||||
bool mipmaps;
|
|
||||||
bool stay_awake;
|
bool stay_awake;
|
||||||
bool force_adb_forward;
|
bool force_adb_forward;
|
||||||
bool disable_screensaver;
|
bool disable_screensaver;
|
||||||
|
@ -103,6 +108,7 @@ struct scrcpy_options {
|
||||||
.data = {SC_MOD_LALT, SC_MOD_LSUPER}, \
|
.data = {SC_MOD_LALT, SC_MOD_LSUPER}, \
|
||||||
.count = 2, \
|
.count = 2, \
|
||||||
}, \
|
}, \
|
||||||
|
.scale_filter = SC_SCALE_FILTER_TRILINEAR, \
|
||||||
.max_size = DEFAULT_MAX_SIZE, \
|
.max_size = DEFAULT_MAX_SIZE, \
|
||||||
.bit_rate = DEFAULT_BIT_RATE, \
|
.bit_rate = DEFAULT_BIT_RATE, \
|
||||||
.max_fps = 0, \
|
.max_fps = 0, \
|
||||||
|
@ -122,7 +128,6 @@ struct scrcpy_options {
|
||||||
.render_expired_frames = false, \
|
.render_expired_frames = false, \
|
||||||
.prefer_text = false, \
|
.prefer_text = false, \
|
||||||
.window_borderless = false, \
|
.window_borderless = false, \
|
||||||
.mipmaps = true, \
|
|
||||||
.stay_awake = false, \
|
.stay_awake = false, \
|
||||||
.force_adb_forward = false, \
|
.force_adb_forward = false, \
|
||||||
.disable_screensaver = false, \
|
.disable_screensaver = false, \
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include "icon.xpm"
|
#include "icon.xpm"
|
||||||
#include "scrcpy.h"
|
|
||||||
#include "tiny_xpm.h"
|
#include "tiny_xpm.h"
|
||||||
#include "video_buffer.h"
|
#include "video_buffer.h"
|
||||||
#include "util/log.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,
|
struct size frame_size, bool always_on_top,
|
||||||
int16_t window_x, int16_t window_y, uint16_t window_width,
|
int16_t window_x, int16_t window_y, uint16_t window_width,
|
||||||
uint16_t window_height, bool window_borderless,
|
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->frame_size = frame_size;
|
||||||
screen->rotation = rotation;
|
screen->rotation = rotation;
|
||||||
if (rotation) {
|
if (rotation) {
|
||||||
|
@ -247,8 +246,8 @@ screen_init_rendering(struct screen *screen, const char *window_title,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = sc_frame_texture_init(&screen->ftex, screen->renderer, mipmaps,
|
bool ok = sc_frame_texture_init(&screen->ftex, screen->renderer,
|
||||||
frame_size);
|
scale_filter, frame_size);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGC("Could not init frame texture");
|
LOGC("Could not init frame texture");
|
||||||
SDL_DestroyRenderer(screen->renderer);
|
SDL_DestroyRenderer(screen->renderer);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "coords.h"
|
#include "coords.h"
|
||||||
#include "frame_texture.h"
|
#include "frame_texture.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
#include "scrcpy.h"
|
||||||
|
|
||||||
struct video_buffer;
|
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,
|
struct size frame_size, bool always_on_top,
|
||||||
int16_t window_x, int16_t window_y, uint16_t window_width,
|
int16_t window_x, int16_t window_y, uint16_t window_width,
|
||||||
uint16_t window_height, bool window_borderless,
|
uint16_t window_height, bool window_borderless,
|
||||||
uint8_t rotation, bool mipmaps);
|
uint8_t rotation, enum sc_scale_filter scale_filter);
|
||||||
|
|
||||||
// show the window
|
// show the window
|
||||||
void
|
void
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue