For anyone interested, I have attached a patch for the Cairo plot
driver which speeds up plotting to the xcairo device considerably,
with the caveat that the plot contents will not appear in the plot
window until a flush occurs by one of:
- A call to plflush
- The end of the page is reached (e.g., pleop, plenv to start a new
page, plend/plend1 to end the plot stream)
This patch puts the behavior of the xcairo device somewhere between
the xwin driver which updates the plot display as it is made and the
qtwidget device which does not display the plot until the end of a
page.
The rendering speedup is attained by rendering the plot to an
off-screen surface and only updating the visible window when
requested. With this patch applied, the PLplot examples render as
fast or faster on my system (64bit Linux, Cairo 1.8.6) with the xcairo
device as they do with the xwin device, without any flickering and
with all anti-aliasing enabled.
The compiled PLplot examples illustrate the speedup (particularly
examples 11, 16 and 20) and flicker-free rendering (example 17) quite
nicely. The shortcoming of not seeing the plot updates until a flush
becomes most noticeable when using the xcairo driver interactively,
say from an interactive Octave, OCaml or Python session. This lack of
interactive updates could be worked around with threading similar to
the pthread use in the xwin driver. The xwin threading code is quite
lengthy and complicated though, so this would likely be a fairly
significant task.
I have been using this patch locally for about 6 months. I find it
makes the xcairo device much more useful for me. The speedup provided
by the off-screen rendering allows me to use the xcairo and its
improved rendering quality where I would have formerly used xwin due
to its impressive speed.
All that said, I would like to ask for comments from others on this
patch before applying it to PLplot. I had asked a few other
developers for comments on a similar patch several months ago, with
the main concerns voiced at the time centering around the lack of
visible updates as a plot is made unless plflush is called or the plot
page ends. This is a significant visible change to how the xcairo
device works. I intended to bring the discussion of this on-list at
that time, but clearly this was delayed by a few months!
Hez
--
Hezekiah M. Carty
Graduate Research Assistant
University of Maryland
Department of Atmospheric and Oceanic Science
diff --git a/drivers/cairo.c b/drivers/cairo.c
index af670ce..0d048b8 100644
--- a/drivers/cairo.c
+++ b/drivers/cairo.c
@@ -96,6 +96,8 @@ typedef struct {
short upDown;
float fontSize;
#if defined(PLD_xcairo)
+ cairo_surface_t *cairoSurface_X;
+ cairo_t *cairoContext_X;
short exit_event_loop;
Display *XDisplay;
Window XWindow;
@@ -1405,7 +1407,11 @@ static signed int xcairo_init_cairo(PLStream *pls)
/* Create an cairo surface & context that are associated with the X window. */
defaultVisual = DefaultVisual(aStream->XDisplay, 0);
/* Dimension units are pixels from cairo documentation. */
- aStream->cairoSurface = cairo_xlib_surface_create(aStream->XDisplay, aStream->XWindow, defaultVisual, pls->xlength, pls->ylength);
+ /* This is the X window Cairo surface. */
+ aStream->cairoSurface_X = cairo_xlib_surface_create(aStream->XDisplay, aStream->XWindow, defaultVisual, pls->xlength, pls->ylength);
+ aStream->cairoContext_X = cairo_create(aStream->cairoSurface_X);
+ /* This is the Cairo surface PLplot will actually plot to. */
+ aStream->cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, pls->xlength, pls->ylength);
aStream->cairoContext = cairo_create(aStream->cairoSurface);
/* Invert the surface so that the graphs are drawn right side up. */
@@ -1466,6 +1472,18 @@ void plD_init_xcairo(PLStream *pls)
}
+/*---------------------------------------------------------------------
+ blit_to_x()
+
+ Blit the offscreen image to the X window.
+ ---------------------------------------------------------------------*/
+
+void blit_to_x(PLCairo *aStream)
+{
+ cairo_set_source_surface(aStream->cairoContext_X, aStream->cairoSurface, 0.0, 0.0);
+ cairo_paint(aStream->cairoContext_X);
+}
+
/*----------------------------------------------------------------------
plD_bop_xcairo()
@@ -1510,6 +1528,9 @@ void plD_eop_xcairo(PLStream *pls)
if (aStream->xdrawable_mode)
return;
+ /* Blit the offscreen image to the X window. */
+ blit_to_x(aStream);
+
XFlush(aStream->XDisplay);
/* Only pause if nopause is unset. */
@@ -1536,8 +1557,8 @@ void plD_eop_xcairo(PLStream *pls)
aStream->exit_event_loop = 1;
break;
case Expose:
- plD_bop_cairo(pls);
- plRemakePlot(pls);
+ /* Blit the image again after an expose event. */
+ blit_to_x(aStream);
XFlush(aStream->XDisplay);
break;
}
@@ -1560,6 +1581,10 @@ void plD_tidy_xcairo(PLStream *pls)
plD_tidy_cairo(pls);
+ /* Also free up the Cairo X surface and context */
+ cairo_destroy(aStream->cairoContext_X);
+ cairo_surface_destroy(aStream->cairoSurface_X);
+
if (aStream->xdrawable_mode)
return;
@@ -1586,6 +1611,7 @@ void plD_esc_xcairo(PLStream *pls, PLINT op, void *ptr)
switch(op)
{
case PLESC_FLUSH: /* forced update of the window */
+ blit_to_x(aStream);
XFlush(aStream->XDisplay);
break;
case PLESC_GETC: /* get cursor position */
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel