Skip to content

Commit 42780d0

Browse files
lpkrugerrom1v
authored andcommitted
Reset renderer on hidpi scaling change
Moving a window between hidpi and non-hidpi monitors is not correctly handled by SDL. Detect when this happens, and recreate the renderer. Fixes <#15> Signed-off-by: Romain Vimont <rom@rom1v.com>
1 parent 492668e commit 42780d0

File tree

2 files changed

+69
-18
lines changed

2 files changed

+69
-18
lines changed

app/src/screen.c

+65-18
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,44 @@ create_texture(SDL_Renderer *renderer, struct size frame_size) {
134134
frame_size.width, frame_size.height);
135135
}
136136

137+
static void
138+
screen_get_sizes(struct screen *screen, struct screen_sizes *out) {
139+
int ww, wh, dw, dh;
140+
SDL_GetWindowSize(screen->window, &ww, &wh);
141+
SDL_GL_GetDrawableSize(screen->window, &dw, &dh);
142+
out->window.width = ww;
143+
out->window.height = wh;
144+
out->window.width = dw;
145+
out->window.height = dh;
146+
}
147+
148+
// This may be called more than once to work around SDL bugs
149+
static bool
150+
screen_init_renderer_and_texture(struct screen *screen) {
151+
screen->renderer = SDL_CreateRenderer(screen->window, -1,
152+
SDL_RENDERER_ACCELERATED);
153+
if (!screen->renderer) {
154+
LOGC("Could not create renderer: %s", SDL_GetError());
155+
return false;
156+
}
157+
158+
if (SDL_RenderSetLogicalSize(screen->renderer, screen->frame_size.width,
159+
screen->frame_size.height)) {
160+
LOGE("Could not set renderer logical size: %s", SDL_GetError());
161+
return false;
162+
}
163+
164+
screen->texture = create_texture(screen->renderer, screen->frame_size);
165+
if (!screen->texture) {
166+
LOGC("Could not create texture: %s", SDL_GetError());
167+
return false;
168+
}
169+
170+
screen_get_sizes(screen, &screen->sizes);
171+
172+
return true;
173+
}
174+
137175
bool
138176
screen_init_rendering(struct screen *screen, const char *window_title,
139177
struct size frame_size, bool always_on_top) {
@@ -161,21 +199,6 @@ screen_init_rendering(struct screen *screen, const char *window_title,
161199
return false;
162200
}
163201

164-
screen->renderer = SDL_CreateRenderer(screen->window, -1,
165-
SDL_RENDERER_ACCELERATED);
166-
if (!screen->renderer) {
167-
LOGC("Could not create renderer: %s", SDL_GetError());
168-
screen_destroy(screen);
169-
return false;
170-
}
171-
172-
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width,
173-
frame_size.height)) {
174-
LOGE("Could not set renderer logical size: %s", SDL_GetError());
175-
screen_destroy(screen);
176-
return false;
177-
}
178-
179202
SDL_Surface *icon = read_xpm(icon_xpm);
180203
if (icon) {
181204
SDL_SetWindowIcon(screen->window, icon);
@@ -186,9 +209,7 @@ screen_init_rendering(struct screen *screen, const char *window_title,
186209

187210
LOGI("Initial texture: %" PRIu16 "x%" PRIu16, frame_size.width,
188211
frame_size.height);
189-
screen->texture = create_texture(screen->renderer, frame_size);
190-
if (!screen->texture) {
191-
LOGC("Could not create texture: %s", SDL_GetError());
212+
if (!screen_init_renderer_and_texture(screen)) {
192213
screen_destroy(screen);
193214
return false;
194215
}
@@ -277,8 +298,34 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) {
277298
return true;
278299
}
279300

301+
// workaround for <https://github.com/Genymobile/scrcpy/issues/15>
302+
static inline bool
303+
screen_fix_hidpi(struct screen *screen) {
304+
struct screen_sizes cur;
305+
screen_get_sizes(screen, &cur);
306+
307+
struct screen_sizes *prev = &screen->sizes;
308+
309+
bool width_ratio_changed = cur.window.width * prev->drawable.width !=
310+
cur.drawable.width * prev->window.width;
311+
bool height_ratio_changed = cur.window.height * prev->drawable.height !=
312+
cur.drawable.height * prev->window.height;
313+
if (width_ratio_changed || height_ratio_changed) {
314+
SDL_DestroyTexture(screen->texture);
315+
SDL_DestroyRenderer(screen->renderer);
316+
if (!screen_init_renderer_and_texture(screen)) {
317+
screen->texture = NULL;
318+
screen->renderer = NULL;
319+
return false;
320+
}
321+
}
322+
323+
return true;
324+
}
325+
280326
void
281327
screen_window_resized(struct screen *screen) {
328+
screen_fix_hidpi(screen);
282329
screen_render(screen);
283330
}
284331

app/src/screen.h

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ struct screen {
2020
bool has_frame;
2121
bool fullscreen;
2222
bool no_window;
23+
struct screen_sizes {
24+
struct size window;
25+
struct size drawable;
26+
} sizes;
2327
};
2428

2529
#define SCREEN_INITIALIZER { \

0 commit comments

Comments
 (0)