|
|
|
@ -1,8 +1,9 @@
|
|
|
|
|
#include "screen.h"
|
|
|
|
|
|
|
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <SDL2/SDL.h>
|
|
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "compat.h"
|
|
|
|
|
#include "icon.xpm"
|
|
|
|
|
#include "lock_util.h"
|
|
|
|
@ -12,11 +13,11 @@
|
|
|
|
|
|
|
|
|
|
#define DISPLAY_MARGINS 96
|
|
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
|
bool
|
|
|
|
|
sdl_init_and_configure(void) {
|
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO)) {
|
|
|
|
|
LOGC("Could not initialize SDL: %s", SDL_GetError());
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
atexit(SDL_Quit);
|
|
|
|
@ -36,7 +37,7 @@ sdl_init_and_configure(void) {
|
|
|
|
|
// Do not disable the screensaver when scrcpy is running
|
|
|
|
|
SDL_EnableScreenSaver();
|
|
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get the window size in a struct size
|
|
|
|
@ -75,7 +76,7 @@ set_window_size(struct screen *screen, struct size new_size) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get the preferred display bounds (i.e. the screen bounds with some margins)
|
|
|
|
|
static SDL_bool
|
|
|
|
|
static bool
|
|
|
|
|
get_preferred_display_bounds(struct size *bounds) {
|
|
|
|
|
SDL_Rect rect;
|
|
|
|
|
#ifdef SCRCPY_SDL_HAS_GET_DISPLAY_USABLE_BOUNDS
|
|
|
|
@ -85,12 +86,12 @@ get_preferred_display_bounds(struct size *bounds) {
|
|
|
|
|
#endif
|
|
|
|
|
if (GET_DISPLAY_BOUNDS(0, &rect)) {
|
|
|
|
|
LOGW("Could not get display usable bounds: %s", SDL_GetError());
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bounds->width = MAX(0, rect.w - DISPLAY_MARGINS);
|
|
|
|
|
bounds->height = MAX(0, rect.h - DISPLAY_MARGINS);
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return the optimal size of the window, with the following constraints:
|
|
|
|
@ -107,8 +108,8 @@ get_optimal_size(struct size current_size, struct size frame_size) {
|
|
|
|
|
|
|
|
|
|
struct size display_size;
|
|
|
|
|
// 32 bits because we need to multiply two 16 bits values
|
|
|
|
|
Uint32 w;
|
|
|
|
|
Uint32 h;
|
|
|
|
|
uint32_t w;
|
|
|
|
|
uint32_t h;
|
|
|
|
|
|
|
|
|
|
if (!get_preferred_display_bounds(&display_size)) {
|
|
|
|
|
// cannot get display bounds, do not constraint the size
|
|
|
|
@ -119,7 +120,7 @@ get_optimal_size(struct size current_size, struct size frame_size) {
|
|
|
|
|
h = MIN(current_size.height, display_size.height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_bool keep_width = frame_size.width * h > frame_size.height * w;
|
|
|
|
|
bool keep_width = frame_size.width * h > frame_size.height * w;
|
|
|
|
|
if (keep_width) {
|
|
|
|
|
// remove black borders on top and bottom
|
|
|
|
|
h = frame_size.height * w / frame_size.width;
|
|
|
|
@ -159,13 +160,13 @@ create_texture(SDL_Renderer *renderer, struct size frame_size) {
|
|
|
|
|
frame_size.width, frame_size.height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
|
bool
|
|
|
|
|
screen_init_rendering(struct screen *screen, const char *device_name,
|
|
|
|
|
struct size frame_size, SDL_bool always_on_top) {
|
|
|
|
|
struct size frame_size, bool always_on_top) {
|
|
|
|
|
screen->frame_size = frame_size;
|
|
|
|
|
|
|
|
|
|
struct size window_size = get_initial_optimal_size(frame_size);
|
|
|
|
|
Uint32 window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
|
|
|
|
uint32_t window_flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
|
|
|
|
#ifdef HIDPI_SUPPORT
|
|
|
|
|
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
|
|
|
|
#endif
|
|
|
|
@ -184,7 +185,7 @@ screen_init_rendering(struct screen *screen, const char *device_name,
|
|
|
|
|
window_flags);
|
|
|
|
|
if (!screen->window) {
|
|
|
|
|
LOGC("Could not create window: %s", SDL_GetError());
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
screen->renderer = SDL_CreateRenderer(screen->window, -1,
|
|
|
|
@ -192,21 +193,21 @@ screen_init_rendering(struct screen *screen, const char *device_name,
|
|
|
|
|
if (!screen->renderer) {
|
|
|
|
|
LOGC("Could not create renderer: %s", SDL_GetError());
|
|
|
|
|
screen_destroy(screen);
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SDL_RenderSetLogicalSize(screen->renderer, frame_size.width,
|
|
|
|
|
frame_size.height)) {
|
|
|
|
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
|
|
|
|
screen_destroy(screen);
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_Surface *icon = read_xpm(icon_xpm);
|
|
|
|
|
if (!icon) {
|
|
|
|
|
LOGE("Could not load icon: %s", SDL_GetError());
|
|
|
|
|
screen_destroy(screen);
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
SDL_SetWindowIcon(screen->window, icon);
|
|
|
|
|
SDL_FreeSurface(icon);
|
|
|
|
@ -217,10 +218,10 @@ screen_init_rendering(struct screen *screen, const char *device_name,
|
|
|
|
|
if (!screen->texture) {
|
|
|
|
|
LOGC("Could not create texture: %s", SDL_GetError());
|
|
|
|
|
screen_destroy(screen);
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -242,14 +243,14 @@ screen_destroy(struct screen *screen) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recreate the texture and resize the window if the frame size has changed
|
|
|
|
|
static SDL_bool
|
|
|
|
|
static bool
|
|
|
|
|
prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
|
|
|
|
if (screen->frame_size.width != new_frame_size.width
|
|
|
|
|
|| screen->frame_size.height != new_frame_size.height) {
|
|
|
|
|
if (SDL_RenderSetLogicalSize(screen->renderer, new_frame_size.width,
|
|
|
|
|
new_frame_size.height)) {
|
|
|
|
|
LOGE("Could not set renderer logical size: %s", SDL_GetError());
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// frame dimension changed, destroy texture
|
|
|
|
@ -257,9 +258,9 @@ prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
|
|
|
|
|
|
|
|
|
struct size current_size = get_window_size(screen);
|
|
|
|
|
struct size target_size = {
|
|
|
|
|
(Uint32) current_size.width * new_frame_size.width
|
|
|
|
|
(uint32_t) current_size.width * new_frame_size.width
|
|
|
|
|
/ screen->frame_size.width,
|
|
|
|
|
(Uint32) current_size.height * new_frame_size.height
|
|
|
|
|
(uint32_t) current_size.height * new_frame_size.height
|
|
|
|
|
/ screen->frame_size.height,
|
|
|
|
|
};
|
|
|
|
|
target_size = get_optimal_size(target_size, new_frame_size);
|
|
|
|
@ -272,11 +273,11 @@ prepare_for_frame(struct screen *screen, struct size new_frame_size) {
|
|
|
|
|
screen->texture = create_texture(screen->renderer, new_frame_size);
|
|
|
|
|
if (!screen->texture) {
|
|
|
|
|
LOGC("Could not create texture: %s", SDL_GetError());
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// write the frame into the texture
|
|
|
|
@ -288,20 +289,20 @@ update_texture(struct screen *screen, const AVFrame *frame) {
|
|
|
|
|
frame->data[2], frame->linesize[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_bool
|
|
|
|
|
bool
|
|
|
|
|
screen_update_frame(struct screen *screen, struct video_buffer *vb) {
|
|
|
|
|
mutex_lock(vb->mutex);
|
|
|
|
|
const AVFrame *frame = video_buffer_consume_rendered_frame(vb);
|
|
|
|
|
struct size new_frame_size = {frame->width, frame->height};
|
|
|
|
|
if (!prepare_for_frame(screen, new_frame_size)) {
|
|
|
|
|
mutex_unlock(vb->mutex);
|
|
|
|
|
return SDL_FALSE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
update_texture(screen, frame);
|
|
|
|
|
mutex_unlock(vb->mutex);
|
|
|
|
|
|
|
|
|
|
screen_render(screen);
|
|
|
|
|
return SDL_TRUE;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -317,7 +318,7 @@ screen_switch_fullscreen(struct screen *screen) {
|
|
|
|
|
// going to fullscreen, store the current windowed window size
|
|
|
|
|
screen->windowed_window_size = get_native_window_size(screen->window);
|
|
|
|
|
}
|
|
|
|
|
Uint32 new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
|
uint32_t new_mode = screen->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
|
if (SDL_SetWindowFullscreen(screen->window, new_mode)) {
|
|
|
|
|
LOGW("Could not switch fullscreen mode: %s", SDL_GetError());
|
|
|
|
|
return;
|
|
|
|
|