mirror of
https://github.com/Genymobile/scrcpy
synced 2025-08-22 09:57:30 +00:00
Create texture on first frame
The texture was created as soon as the initial video size was known, even before the first frame arrived. However, texture creation will require other data, such as the color range, which is only available once the first frame is received. Therefore, delay texture creation until the first frame.
This commit is contained in:
parent
6a0529ca13
commit
023fad8bad
@ -16,7 +16,6 @@ enum {
|
|||||||
SC_EVENT_USB_DEVICE_DISCONNECTED,
|
SC_EVENT_USB_DEVICE_DISCONNECTED,
|
||||||
SC_EVENT_DEMUXER_ERROR,
|
SC_EVENT_DEMUXER_ERROR,
|
||||||
SC_EVENT_RECORDER_ERROR,
|
SC_EVENT_RECORDER_ERROR,
|
||||||
SC_EVENT_SCREEN_INIT_SIZE,
|
|
||||||
SC_EVENT_TIME_LIMIT_REACHED,
|
SC_EVENT_TIME_LIMIT_REACHED,
|
||||||
SC_EVENT_CONTROLLER_ERROR,
|
SC_EVENT_CONTROLLER_ERROR,
|
||||||
SC_EVENT_AOA_OPEN_ERROR,
|
SC_EVENT_AOA_OPEN_ERROR,
|
||||||
|
@ -208,6 +208,7 @@ sc_screen_update_content_rect(struct sc_screen *screen) {
|
|||||||
static void
|
static void
|
||||||
sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
sc_screen_render(struct sc_screen *screen, bool update_content_rect) {
|
||||||
assert(screen->video);
|
assert(screen->video);
|
||||||
|
assert(screen->has_video_window);
|
||||||
|
|
||||||
if (update_content_rect) {
|
if (update_content_rect) {
|
||||||
sc_screen_update_content_rect(screen);
|
sc_screen_update_content_rect(screen);
|
||||||
@ -264,19 +265,6 @@ sc_screen_frame_sink_open(struct sc_frame_sink *sink,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ctx->width > 0 && ctx->width <= 0xFFFF);
|
|
||||||
assert(ctx->height > 0 && ctx->height <= 0xFFFF);
|
|
||||||
// screen->frame_size is never used before the event is pushed, and the
|
|
||||||
// event acts as a memory barrier so it is safe without mutex
|
|
||||||
screen->frame_size.width = ctx->width;
|
|
||||||
screen->frame_size.height = ctx->height;
|
|
||||||
|
|
||||||
// Post the event on the UI thread (the texture must be created from there)
|
|
||||||
bool ok = sc_push_event(SC_EVENT_SCREEN_INIT_SIZE);
|
|
||||||
if (!ok) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
screen->open = true;
|
screen->open = true;
|
||||||
#endif
|
#endif
|
||||||
@ -327,6 +315,7 @@ sc_screen_init(struct sc_screen *screen,
|
|||||||
const struct sc_screen_params *params) {
|
const struct sc_screen_params *params) {
|
||||||
screen->resize_pending = false;
|
screen->resize_pending = false;
|
||||||
screen->has_frame = false;
|
screen->has_frame = false;
|
||||||
|
screen->has_video_window = false;
|
||||||
screen->fullscreen = false;
|
screen->fullscreen = false;
|
||||||
screen->maximized = false;
|
screen->maximized = false;
|
||||||
screen->minimized = false;
|
screen->minimized = false;
|
||||||
@ -603,22 +592,6 @@ sc_screen_set_orientation(struct sc_screen *screen,
|
|||||||
sc_screen_render(screen, true);
|
sc_screen_render(screen, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
sc_screen_init_size(struct sc_screen *screen) {
|
|
||||||
// Before first frame
|
|
||||||
assert(!screen->has_frame);
|
|
||||||
|
|
||||||
// The requested size is passed via screen->frame_size
|
|
||||||
|
|
||||||
struct sc_size content_size =
|
|
||||||
get_oriented_size(screen->frame_size, screen->orientation);
|
|
||||||
screen->content_size = content_size;
|
|
||||||
|
|
||||||
enum sc_display_result res =
|
|
||||||
sc_display_set_texture_size(&screen->display, screen->frame_size);
|
|
||||||
return res != SC_DISPLAY_RESULT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sc_screen_apply_frame(struct sc_screen *screen) {
|
sc_screen_apply_frame(struct sc_screen *screen) {
|
||||||
assert(screen->video);
|
assert(screen->video);
|
||||||
@ -628,16 +601,22 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|||||||
AVFrame *frame = screen->frame;
|
AVFrame *frame = screen->frame;
|
||||||
struct sc_size new_frame_size = {frame->width, frame->height};
|
struct sc_size new_frame_size = {frame->width, frame->height};
|
||||||
|
|
||||||
if (screen->frame_size.width != new_frame_size.width
|
if (!screen->has_frame
|
||||||
|
|| screen->frame_size.width != new_frame_size.width
|
||||||
|| screen->frame_size.height != new_frame_size.height) {
|
|| screen->frame_size.height != new_frame_size.height) {
|
||||||
// frame dimension changed
|
// frame dimension changed
|
||||||
screen->frame_size = new_frame_size;
|
screen->frame_size = new_frame_size;
|
||||||
|
|
||||||
struct sc_size new_content_size =
|
struct sc_size new_content_size =
|
||||||
get_oriented_size(new_frame_size, screen->orientation);
|
get_oriented_size(new_frame_size, screen->orientation);
|
||||||
set_content_size(screen, new_content_size);
|
if (screen->has_frame) {
|
||||||
|
set_content_size(screen, new_content_size);
|
||||||
sc_screen_update_content_rect(screen);
|
sc_screen_update_content_rect(screen);
|
||||||
|
} else {
|
||||||
|
// This is the first frame
|
||||||
|
screen->has_frame = true;
|
||||||
|
screen->content_size = new_content_size;
|
||||||
|
}
|
||||||
|
|
||||||
enum sc_display_result res =
|
enum sc_display_result res =
|
||||||
sc_display_set_texture_size(&screen->display, screen->frame_size);
|
sc_display_set_texture_size(&screen->display, screen->frame_size);
|
||||||
@ -660,8 +639,9 @@ sc_screen_apply_frame(struct sc_screen *screen) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!screen->has_frame) {
|
assert(screen->has_frame);
|
||||||
screen->has_frame = true;
|
if (!screen->has_video_window) {
|
||||||
|
screen->has_video_window = true;
|
||||||
// this is the very first frame, show the window
|
// this is the very first frame, show the window
|
||||||
sc_screen_show_initial_window(screen);
|
sc_screen_show_initial_window(screen);
|
||||||
|
|
||||||
@ -794,15 +774,6 @@ sc_screen_resize_to_pixel_perfect(struct sc_screen *screen) {
|
|||||||
bool
|
bool
|
||||||
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
||||||
switch (event->type) {
|
switch (event->type) {
|
||||||
case SC_EVENT_SCREEN_INIT_SIZE: {
|
|
||||||
// The initial size is passed via screen->frame_size
|
|
||||||
bool ok = sc_screen_init_size(screen);
|
|
||||||
if (!ok) {
|
|
||||||
LOGE("Could not initialize screen size");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case SC_EVENT_NEW_FRAME: {
|
case SC_EVENT_NEW_FRAME: {
|
||||||
bool ok = sc_screen_update_frame(screen);
|
bool ok = sc_screen_update_frame(screen);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@ -815,11 +786,12 @@ sc_screen_handle_event(struct sc_screen *screen, const SDL_Event *event) {
|
|||||||
if (!screen->video
|
if (!screen->video
|
||||||
&& event->window.event == SDL_WINDOWEVENT_EXPOSED) {
|
&& event->window.event == SDL_WINDOWEVENT_EXPOSED) {
|
||||||
sc_screen_render_novideo(screen);
|
sc_screen_render_novideo(screen);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !video implies !has_frame
|
// !video implies !has_video_window
|
||||||
assert(screen->video || !screen->has_frame);
|
assert(screen->video || !screen->has_video_window);
|
||||||
if (!screen->has_frame) {
|
if (!screen->has_video_window) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ struct sc_screen {
|
|||||||
// rectangle of the content (excluding black borders)
|
// rectangle of the content (excluding black borders)
|
||||||
struct SDL_Rect rect;
|
struct SDL_Rect rect;
|
||||||
bool has_frame;
|
bool has_frame;
|
||||||
|
bool has_video_window;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user