Fix cairo surface flushing and marking in create_surface

This commit is contained in:
Petar Kapriš 2025-10-13 22:02:22 +02:00
parent 94176c8d7c
commit 96087d17a1

33
visor.c
View file

@ -355,8 +355,7 @@ void plane_resize(GtkWidget *widget)
void create_surface(GtkWidget *widget)
{
cairo_t *cr;
// Stop all current drawers
pthread_mutex_lock(&pixmapMutex);
pixmapAvailable = false; // Mark drawing area as unavailable
pthread_mutex_unlock(&pixmapMutex);
@ -367,9 +366,24 @@ void create_surface(GtkWidget *widget)
for (int32_t i = 0; i < thread_count; i++) {
if (threads[i].drawing) {
allWritersStopped = false;
break;
}
}
} while (!allWritersStopped);
// If all drawers hadn't completed, we need to call
// cairo_surface_mark_dirty in the main thread
bool allWritersHadCompleted = true;
for (int32_t i = 0; i < thread_count; i++) {
if (!threads[i].complete) {
allWritersHadCompleted = false;
break;
}
}
if (!allWritersHadCompleted && surface != NULL) {
cairo_surface_mark_dirty(surface);
}
for (int32_t i = 0; i < thread_count; i++) {
threads[i].complete = false;
}
@ -382,20 +396,21 @@ void create_surface(GtkWidget *widget)
gtk_widget_get_width(widget),
gtk_widget_get_height(widget));
cr = cairo_create(surface);
cairo_surface_flush(surface);
int h = cairo_image_surface_get_height(surface);
int w = cairo_image_surface_get_width(surface);
mandelbrot.height = h;
mandelbrot.width = w;
pixmap = cairo_image_surface_get_data(surface);
cairo_surface_mark_dirty(surface);
// Mark the surface as ready to be drawn by memory access
// Then notify other threads to start drawing
// One of these threads will make the corresponding call using
// cairo_surface_mark_dirty, to notify they are all done drawing
cairo_surface_flush(surface);
pixmap = cairo_image_surface_get_data(surface);
// This lock is unnecessary since all other threads are stopped already
pthread_mutex_lock(&pixmapMutex);
pixmapAvailable = true;
pthread_mutex_unlock(&pixmapMutex);
pthread_cond_broadcast(&pixmapCond);
cairo_destroy(cr);
}