GCDC vs DC (was: Re: Automotive-type gauge)

Chris Mellon wrote:

···

On 8/1/07, Andrea Gavana <andrea.gavana@gmail.com> wrote:

You might find my implementation of SpeedMeter useful:

http://xoomer.alice.it/infinity77/eng/freeware.html#speedmeter

I almost finished refactoring my web pages, so you might find some
troubles today or tomorrow... but the code is there :smiley:

Nice work as always Andrea. A one-liner wrapping the DC used for
drawing in a wxGCDC gives very nice anti-aliasing, but makes it quite
a bit slower. Maybe if I can find some time I'll work on a port that's
optimized for wxGraphicsContext. I think it could end up quite faster
than the raster based version.

What kind of optimization can be done when using GCDC instead of DC? Do you
think wx.lib.plot could be made faster, too? plot.py is basically using
DrawLine, DrawLineList, DrawText I think. Are there faster replacements?

Thanks, Christian

Chris Mellon wrote:
> Drawing using wxGC can be very very fast when you ...

Good news.

> leverage the ability to re-use paths with the transforms that wxGC
> exposes because it lets you move the math out of python and into the
> heavily optimized native implementation.

What math? There is math if you need to scale stuff (though if you use
Dc.SetUserScale then Python's not doing that math either. In
FloatCanvas, I use numpy to do the scaling and shifting math, and I
haven't profiled carefully, but I'm pretty sure the math is Much faster
than the drawing.

Scaling, shifting, polygons and arcs not directly supported by wxDC.
Hit testing for non-rectangular regions. Numpy will obviously handle
the math better than pure python, though. wxGC also supports arbitrary
matrix transforms, including rotation, which wxDC doesn't and are slow
to implement in Python.

I was concerned about the time to takes to transfer python data types to
C++, and the DrawXXXList methods are the result of that. However, it
really only makes a difference for DrawPointList (and maybe
DrawLineList), as it turns out that the drawing itself really is the
bottleneck for more complex objects (polygons, etc.). That makes some
sense -- think about the computation it takes to draw and fill a polygon!

The marshaling isn't so much of a problem, but iteration in Python is
much slower than in C++ (several orders of magnitude) and moving loops
out of it is a big win. Psyco can accelerate python loops, too.

How long does it really take to create a path, vs. to draw it?

In my very first SVG implementation I reparsed and re-rendered the SVG
document from the XML with every draw. The first obvious optimization
was to save the SVG document model and doing that saved my about 90%
of my drawing time. The second optimization was to build a drawlist of
pre-built paths and objects instead of re-creating them and that saved
another 90%.

You can get a very large win by pre-caching paths. There's also a
smaller gain from caching graphics objects - wxWidgets will cache them
internally, but wxPython does't know about this so by caching yourself
you can eliminate the creation of the wrapper object.

So far, what I've seen is major performance degradation when switching
to GraphicsContext -- though I do admit that those have being naive
translations.

> It does, however, require a very different drawing model.

Which is key, I guess. Do you have any examples of performance
comparisons of DC and GraphicsContext where the GraphicsContext code is
written carefully?

Nothing that I've benchmarked in any detail. wxGC can render a
thousand vertex polygon in less time than you can practically measure,
though. I've found that in general the cost of drawing with a wxDC is
related to the complexity of the drawing - the number of calls you
have to make. Blitting is almost 0 cost for any size bitmap, for
example.

On the other hand, with wxGC the primary *render* cost is the total
number of pixels pushed. The exact same path will be much faster
rendered at 100x100 vs 1000x1000.

> As the underlying platforms move more toward native vector everything
> you might even end up with a gain -

This is likely true -- the wxMac version uses CoreGraphics, which is
using a drawing model (displayPDF) that is quite similar to
GraphicsContext, and would hope that Apple is making sure it is well
optimized!

However, the current DC implementation is a Vector implementation, just
not nearly as sophisticated a one.

> Gtk in the future is likely to use cairo for all it's drawing,

Right, so DC calls will be translated into Cairo calls anyway, and
GraphicsContext is very similar to the Cairo API, so it can't be any slower.

> and raster operations will be piped through it. Sort of the reverse
> of the current wxGCDC penalty.

This implies that the current wxGCDC implementation used GraphicsContext
to draw each object on a bitmap, then blits that bitmap to the DC --
which would, indeed, explain the performance hit!

I believe on Gtk it does exactly that. On MSW you can create Graphics
objects that draw directly into HDCs, but cairo on Gtk needs a bitmap.
On Gtk, cairo draws directly into the Gtk windows backing store.

···

On 8/2/07, Christopher Barker <Chris.Barker@noaa.gov> wrote:

I really do need to play with GraphicsContext more -- I sure so hope I
can get decent performance out of it.

-CHB

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org