diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/app.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/src/common/app.c b/src/common/app.c index 5350f85..1916c5b 100644 --- a/src/common/app.c +++ b/src/common/app.c @@ -14,6 +14,8 @@ struct user_event_node { struct user_event_node *next; }; +/* `surface` is NULL once the surface is destroyed. A callback may still + * hold the entry then, so only app_runner_free_dead() frees it. */ struct app_surface { struct yasl_surface *surface; struct app_runner *runner; @@ -24,7 +26,6 @@ struct app_surface { struct yasl_vector2i last_size; uint32_t last_scale_120; uint64_t frame_index; - bool frame_in_progress; bool presented; struct app_surface *next; }; @@ -49,7 +50,6 @@ static void app_runner_surface_draw(struct yasl_surface *s, struct yasl_frame *f if (!ar || !ar->desc || !ar->desc->frame) return; - as->frame_in_progress = true; as->presented = false; struct yasl_frame_context ctx = { @@ -75,11 +75,8 @@ static void app_runner_surface_draw(struct yasl_surface *s, struct yasl_frame *f ar->desc->frame(ar->desc->userdata, s, &ctx); - if (as->pacing == YASL_PACING_CONTINUOUS && ar->running) { + if (as->surface && as->pacing == YASL_PACING_CONTINUOUS && ar->running) yasl_surface_schedule_redraw(s); - } - - as->frame_in_progress = false; } static void app_runner_surface_configure(struct yasl_surface *s, struct yasl_geometry geom, void *ud) @@ -104,6 +101,8 @@ static void app_runner_surface_configure(struct yasl_surface *s, struct yasl_geo }; if (ar->desc->event(ar->desc->userdata, &ev) == YASL_APP_QUIT) ar->running = false; + if (!as->surface) + return; } struct yasl_event ev = { @@ -117,7 +116,8 @@ static void app_runner_surface_configure(struct yasl_surface *s, struct yasl_geo if (ar->desc->event(ar->desc->userdata, &ev) == YASL_APP_QUIT) ar->running = false; - yasl_surface_schedule_redraw(s); + if (as->surface) + yasl_surface_schedule_redraw(s); } static void app_runner_surface_close(struct yasl_surface *s, void *ud) @@ -172,19 +172,23 @@ void app_runner_unregister_surface(void *runner, struct yasl_surface *s) return; struct app_runner *ar = runner; struct app_surface *as = s->app_surface; + as->surface = NULL; + s->app_surface = NULL; + ar->surface_count--; +} - struct app_surface **curr = &ar->surfaces; - while (*curr) { - if (*curr == as) { - *curr = as->next; - break; +/* Call only when no callback runs. */ +static void app_runner_free_dead(struct app_runner *ar) +{ + for (struct app_surface **p = &ar->surfaces; *p;) { + struct app_surface *as = *p; + if (as->surface) { + p = &as->next; + continue; } - curr = &(*curr)->next; + *p = as->next; + free(as); } - - ar->surface_count--; - s->app_surface = NULL; - free(as); } bool yasl_frame_present_cpu(struct yasl_frame_context *ctx, @@ -343,7 +347,8 @@ static void app_runner_dispatch_input_events(struct app_runner *ar) { for (struct app_surface *as = ar->surfaces; as && ar->running; as = as->next) { struct yasl_input_event ie; - while (yasl_surface_input_poll(as->surface, &ie) && ar->running) { + while (as->surface && yasl_surface_input_poll(as->surface, &ie) && + ar->running) { if (!ar->desc->event) continue; @@ -473,6 +478,7 @@ int yasl_run(const struct yasl_app_desc *desc) bool has_frame_pacing = (caps & YASL_CAP_FRAME_PACING) != 0; while (runner.running) { + app_runner_free_dead(&runner); if (runner.had_surfaces && runner.surface_count == 0) { runner.running = false; break; @@ -503,7 +509,7 @@ int yasl_run(const struct yasl_app_desc *desc) if (!has_frame_pacing && any_continuous && runner.running) { for (struct app_surface *as = runner.surfaces; as; as = as->next) { - if (as->pacing == YASL_PACING_CONTINUOUS) { + if (as->surface && as->pacing == YASL_PACING_CONTINUOUS) { yasl_surface_schedule_redraw(as->surface); } } @@ -515,10 +521,11 @@ int yasl_run(const struct yasl_app_desc *desc) } /* Destroy any surfaces that were not explicitly destroyed by the application */ - while (runner.surfaces) { - struct yasl_surface *s = runner.surfaces->surface; - yasl_surface_destroy(s); + for (struct app_surface *as = runner.surfaces; as; as = as->next) { + if (as->surface) + yasl_surface_destroy(as->surface); } + app_runner_free_dead(&runner); d->app_runner = NULL; |
