diff --git a/visor.c b/visor.c index ee2b43a..9e5e2f3 100644 --- a/visor.c +++ b/visor.c @@ -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); }