summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/app.c51
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;