On 17 August 2010 11:23, Chris Vine <ch...@cvine.freeserve.co.uk> wrote: > On Tue, 17 Aug 2010 10:01:43 +0100 > James Morris <ja...@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? >> Cheers, >> James. > > Can you avoid redrawing the entire list of rectangles on each expose > event?
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. James. > Chris > > > _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list