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) void create_surface(GtkWidget *widget)
{ {
cairo_t *cr; // Stop all current drawers
pthread_mutex_lock(&pixmapMutex); pthread_mutex_lock(&pixmapMutex);
pixmapAvailable = false; // Mark drawing area as unavailable pixmapAvailable = false; // Mark drawing area as unavailable
pthread_mutex_unlock(&pixmapMutex); pthread_mutex_unlock(&pixmapMutex);
@ -367,9 +366,24 @@ void create_surface(GtkWidget *widget)
for (int32_t i = 0; i < thread_count; i++) { for (int32_t i = 0; i < thread_count; i++) {
if (threads[i].drawing) { if (threads[i].drawing) {
allWritersStopped = false; allWritersStopped = false;
break;
} }
} }
} while (!allWritersStopped); } 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++) { for (int32_t i = 0; i < thread_count; i++) {
threads[i].complete = false; threads[i].complete = false;
} }
@ -382,20 +396,21 @@ void create_surface(GtkWidget *widget)
gtk_widget_get_width(widget), gtk_widget_get_width(widget),
gtk_widget_get_height(widget)); gtk_widget_get_height(widget));
cr = cairo_create(surface);
cairo_surface_flush(surface);
int h = cairo_image_surface_get_height(surface); int h = cairo_image_surface_get_height(surface);
int w = cairo_image_surface_get_width(surface); int w = cairo_image_surface_get_width(surface);
mandelbrot.height = h; mandelbrot.height = h;
mandelbrot.width = w; 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); pthread_mutex_lock(&pixmapMutex);
pixmapAvailable = true; pixmapAvailable = true;
pthread_mutex_unlock(&pixmapMutex); pthread_mutex_unlock(&pixmapMutex);
pthread_cond_broadcast(&pixmapCond); pthread_cond_broadcast(&pixmapCond);
cairo_destroy(cr);
} }