Compare commits

...

3 Commits

Author SHA1 Message Date
Romain Vimont
2e425e6605 Fix HiDPI issues on secondary screen
Reset the renderer and texture on display scaling change.

FIXME problem with texture (see FIXME in code)

Co-authored-by: Louis Kruger <louisk@gmail.com>
2020-04-24 23:50:42 +02:00
Romain Vimont
f3b7712ea2 Add a mechanism to report errors on event handling
This paves the way to workaround HiDPI issues, which may recreate the
renderer and texture (which may fail) on window event.
2020-04-24 23:35:42 +02:00
Romain Vimont
04a31ef7b9 Remove HIDPI_SUPPORT compilation flag
We never need to build without HiDPI support.
2020-04-24 23:02:58 +02:00
5 changed files with 103 additions and 11 deletions

View File

@ -116,9 +116,6 @@ conf.set('DEFAULT_LOCK_VIDEO_ORIENTATION', '-1') # -1: unlocked
# overridden by option --bit-rate
conf.set('DEFAULT_BIT_RATE', '8000000') # 8Mbps
# enable High DPI support
conf.set('HIDPI_SUPPORT', get_option('hidpi_support'))
# disable console on Windows
conf.set('WINDOWS_NOCONSOLE', get_option('windows_noconsole'))

View File

@ -128,6 +128,7 @@ enum event_result {
EVENT_RESULT_CONTINUE,
EVENT_RESULT_STOPPED_BY_USER,
EVENT_RESULT_STOPPED_BY_EOS,
EVENT_RESULT_STOPPED_BY_ERROR,
};
static enum event_result
@ -150,7 +151,9 @@ handle_event(SDL_Event *event, bool control) {
}
break;
case SDL_WINDOWEVENT:
screen_handle_window_event(&screen, &event->window);
if (!screen_handle_window_event(&screen, &event->window)) {
return EVENT_RESULT_STOPPED_BY_ERROR;
}
break;
case SDL_TEXTINPUT:
if (!control) {
@ -222,6 +225,9 @@ event_loop(bool display, bool control) {
case EVENT_RESULT_STOPPED_BY_EOS:
LOGW("Device disconnected");
return false;
case EVENT_RESULT_STOPPED_BY_ERROR:
LOGC("Stopping due to unrecoverable error");
return false;
case EVENT_RESULT_CONTINUE:
break;
}

View File

@ -217,10 +217,9 @@ screen_init_rendering(struct screen *screen, const char *window_title,
struct size window_size =
get_initial_optimal_size(content_size, window_width, window_height);
uint32_t window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
#ifdef HIDPI_SUPPORT
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
uint32_t window_flags = SDL_WINDOW_HIDDEN
| SDL_WINDOW_RESIZABLE
| SDL_WINDOW_ALLOW_HIGHDPI;
if (always_on_top) {
#ifdef SCRCPY_SDL_HAS_WINDOW_ALWAYS_ON_TOP
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
@ -310,6 +309,11 @@ screen_init_rendering(struct screen *screen, const char *window_title,
screen->windowed_window_size = window_size;
struct scale_ratio *rw = &screen->scale.w;
struct scale_ratio *rh = &screen->scale.h;
SDL_GetWindowSize(screen->window, &rw->window, &rh->window);
SDL_GL_GetDrawableSize(screen->window, &rw->drawable, &rh->drawable);
return true;
}
@ -519,11 +523,74 @@ screen_resize_to_pixel_perfect(struct screen *screen) {
content_size.height);
}
void
bool
screen_fix_hidpi(struct screen *screen) {
// If the scale ratio has changed, recreate the renderer to fix HiDPI issues
// <https://github.com/Genymobile/scrcpy/issues/15>
int ww, wh, dw, dh;
SDL_GetWindowSize(screen->window, &ww, &wh);
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
struct scale_ratio *rw = &screen->scale.w;
struct scale_ratio *rh = &screen->scale.h;
if (ww * rw->drawable == dw * rw->window &&
wh * rh->drawable == dh * rh->window) {
// same ratio, both horizontally and vertically, nothing to do
return true;
}
// update the current scale
rw->window = ww;
rh->window = wh;
rw->drawable = dw;
rh->drawable = dh;
if (screen->texture) {
SDL_DestroyTexture(screen->texture);
}
if (screen->renderer) {
SDL_DestroyRenderer(screen->renderer);
}
screen->renderer = SDL_CreateRenderer(screen->window, -1,
SDL_RENDERER_ACCELERATED);
if (!screen->renderer) {
LOGC("Could not create renderer: %s", SDL_GetError());
return false;
}
struct size content_size = screen->content_size;
if (SDL_RenderSetLogicalSize(screen->renderer, content_size.width,
content_size.height)) {
LOGE("Could not set renderer logical size: %s", SDL_GetError());
SDL_DestroyRenderer(screen->renderer);
return false;
}
// FIXME this is wrong, we must update the last frame to the new texture,
// but we don't have it anymore!
screen->texture = create_texture(screen);
if (!screen->texture) {
LOGC("Could not create texture: %s", SDL_GetError());
SDL_DestroyRenderer(screen->renderer);
return false;
}
LOGD("Renderer and texture reset");
return true;
}
bool
screen_handle_window_event(struct screen *screen,
const SDL_WindowEvent *event) {
switch (event->event) {
case SDL_WINDOWEVENT_EXPOSED:
if (!screen_fix_hidpi(screen)) {
// unrecoverable
return false;
}
screen_render(screen);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
@ -559,6 +626,8 @@ screen_handle_window_event(struct screen *screen,
apply_windowed_size(screen);
break;
}
return true;
}
struct point

View File

@ -13,6 +13,11 @@
struct video_buffer;
struct scale_ratio {
int window;
int drawable;
};
struct screen {
SDL_Window *window;
SDL_Renderer *renderer;
@ -33,6 +38,11 @@ struct screen {
bool maximized;
bool no_window;
bool mipmaps;
struct {
struct scale_ratio w;
struct scale_ratio h;
} scale;
};
#define SCREEN_INITIALIZER { \
@ -63,6 +73,16 @@ struct screen {
.maximized = false, \
.no_window = false, \
.mipmaps = false, \
.scale = { \
.w = { \
.window = 0, \
.drawable = 0, \
}, \
.h = { \
.window = 0, \
.drawable = 0, \
}, \
} \
}
// initialize default values
@ -111,7 +131,8 @@ void
screen_set_rotation(struct screen *screen, unsigned rotation);
// react to window events
void
// return true on success, false on unrecoverable error
bool
screen_handle_window_event(struct screen *screen, const SDL_WindowEvent *event);
// convert point from window coordinates to frame coordinates

View File

@ -4,6 +4,5 @@ option('crossbuild_windows', type: 'boolean', value: false, description: 'Build
option('windows_noconsole', type: 'boolean', value: false, description: 'Disable console on Windows (pass -mwindows flag)')
option('prebuilt_server', type: 'string', description: 'Path of the prebuilt server')
option('portable', type: 'boolean', value: false, description: 'Use scrcpy-server from the same directory as the scrcpy executable')
option('hidpi_support', type: 'boolean', value: true, description: 'Enable High DPI support')
option('server_debugger', type: 'boolean', value: false, description: 'Run a server debugger and wait for a client to be attached')
option('server_debugger_method', type: 'combo', choices: ['old', 'new'], value: 'new', description: 'Select the debugger method (Android < 9: "old", Android >= 9: "new")')