Re: Performance issues of GDK deprecation in favour of Cairo

On 17 August 2010 11:23, Chris Vine <chris cvine freeserve co uk> wrote:
On Tue, 17 Aug 2010 10:01:43 +0100
James Morris <james jwm-art net> wrote:

I see that some GDK drawing functions and graphics contexts have been
deprecated in favour of using Cairo.

Yesterday I spent a few hours *removing* Cairo code from my fledgling
GTK application and replacing it with gdk_draw_rectangle,
gdk_gc_set_rgb_fg_color, and gdk_gc_set_function. I did this for
performance reasons[1]

I am wondering if my approach to drawing is wrong however and if a
better approach might yield less CPU usage?

It begins with a 33ms timeout. The timeout callback calls
gtk_widget_queue_draw on the window and the drawing area.

(Imagine rectangles appearing each time a note is played in a piece of
music and disappearing when that note ends.)

In the expose event callback a linked-list of rectangles is
maintained. Rectangles are added to the list and removed from the list
as notes start and end (The application is an experimental MIDI
sequencer/arpeggiator operating in real time).

Each and every time the expose event callback is called (every 33ms)
the background and the entire list of rectangles is drawn as well as
various maintenance functions performed on the list.

The documentation of gdk_cairo_create seems to suggest this is the
only way of doing it when it says:

"Note that due to double-buffering, Cairo contexts created in a GTK+
expose event handler cannot be cached and reused between different
expose events."

Is it possible to do this any other way?

Can you avoid redrawing the entire list of rectangles on each expose

Yes this is what I'm hoping. Though I've been a bit mixed up with how
Cairo and GTK work together.

When drawing in an expose event callback, you would normally clip to
the rectangle representing the "dirty" area (the area enclosed by
event->area.x, event->area.y, event->area.width, event->area.height).
You could then only call gdk_window_invalidate_rect() or
gdk_window_invalidate_region() on the particular parts of the
particular GdkWindow object(s) which need redrawing.

Right. I think I'm starting to see where I went wrong. Though say it
is a real expose event (ie not due to the timeout) which has erased
some rectangles. Do I need to redraw the dirty area with calls to
cairo, that is, I will still need to maintain a list of rectangles
that currently exist?

What about drawing via cairo to a pixbuf and using that for the (real)
expose events?

In your particular case, unless the notes "move", you could just
invalidate only the areas representing the notes which have just begun
or ended. Depending on your program logic you may be able to dispense
with the timeout entirely: your active code which handles note changes
could call gdk_window_invalidate_* on a selective basis as necessary.

No the notes don't move. Other rectangles can be moved around and
resized by the user.

I don't think I can dispense with the timeout. The processing of the
events happens in a separate real time thread. You can't block RT
threads with mutexes etc (and calling GUI code within it is not
allowed). The GUI can't know when notes are coming and consequently
has to check a lock-free ring buffer every 33ms (I chose that as a
reasonable period).

Sorry... Some of my questions are due to only ever skimming the
documentation for the minimum I need.

Thanks for your help.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]