- /* draw background color */
-
- draw_context->save ();
- draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- draw_context->clip ();
- draw_context->set_operator (Cairo::OPERATOR_SOURCE);
- set_source_rgba (draw_context, _bg_color);
- draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- draw_context->fill ();
- draw_context->restore ();
-
- /* render canvas */
-
- render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
-
-#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_GTK_CANVAS
- /* now blit our private surface back to the GDK one */
-
- window_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
- window_context->clip ();
- window_context->set_source (canvas_image, 0, 0);
- window_context->set_operator (Cairo::OPERATOR_SOURCE);
- window_context->paint ();
+ draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+ draw_context->clip();
+
+#ifdef __APPLE__
+ /* group calls cairo_quartz_surface_create() which
+ * effectively uses a CGBitmapContext + image-surface
+ *
+ * This avoids expensive argb32_image_mark_image() during drawing.
+ * Although the final paint() operation still takes the slow path
+ * through image_mark_image instead of ColorMaskCopyARGB888_sse :(
+ *
+ * profiling indicates a speed up of factor 2. (~ 5-10ms render time,
+ * instead of 10-20ms, which is still slow compared to XCB and win32 surfaces (~0.2 ms)
+ *
+ * Fixing this for good likely involves changes to GdkQuartzWindow, GdkQuartzView
+ */
+ draw_context->push_group ();
+#endif
+
+ /* draw background color */
+ draw_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+ Gtkmm2ext::set_source_rgba (draw_context, _bg_color);
+ draw_context->fill ();
+
+ /* render canvas */
+ if ( _single_exposure ) {
+
+ Canvas::render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
+
+ } else {
+ GdkRectangle* rects;
+ gint nrects;
+
+ gdk_region_get_rectangles (ev->region, &rects, &nrects);
+ for (gint n = 0; n < nrects; ++n) {
+ draw_context->set_identity_matrix(); //reset the cairo matrix, just in case someone left it transformed after drawing ( cough )
+ Canvas::render (Rect (rects[n].x, rects[n].y, rects[n].x + rects[n].width, rects[n].y + rects[n].height), draw_context);
+ }
+ g_free (rects);
+ }
+
+#ifdef __APPLE__
+ draw_context->pop_group_to_source ();
+ draw_context->paint ();
+#endif
+
+#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
+ if (getenv("ARDOUR_IMAGE_SURFACE")) {
+#endif
+#if defined USE_CAIRO_IMAGE_SURFACE || defined OPTIONAL_CAIRO_IMAGE_SURFACE
+ /* now blit our private surface back to the GDK one */
+
+ window_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+ window_context->clip ();
+ window_context->set_source (canvas_image, 0, 0);
+ window_context->set_operator (Cairo::OPERATOR_SOURCE);
+ window_context->paint ();
+#endif
+#ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
+ }
+#endif
+
+#ifdef CANVAS_PROFILE
+ const int64_t end = g_get_monotonic_time ();
+ const int64_t elapsed = end - start;
+ printf ("GtkCanvas::on_expose_event %f ms\n", elapsed / 1000.f);