[Swfdec] redraw priorities
Benjamin Otte
otte at gnome.org
Mon Mar 31 02:10:01 PDT 2008
Hey,
I've recently investigated problems Swfdec has when running
cpu-intensive Flash files and could need some suggestions on how to
best fix it. There should be other apps that have had the same problem
after all. During a run of Swfdec (either stand-alone or as part of a
browser), there's the following events happening:
1. write audio
2. user interaction
3. repaint
4. advance the state of the player ("next frame")
The naïve idea that current Swfdec uses is ordering priorites 1 > 4 >
2 > 3. However, this causes problems if going to the next frame takes
longer than it should take, so that you get no chance to update the
screen or do user interaction (oops).
Adobe's player orders the priorities 1 > 2 > 3 > 4, effectively using
an idle handler to go to the next frame. However, this is unfortunate
as it leads to animations slowing down when maxing CPU and also causes
audio to go out of sync as audio due still runs in real time because
of its high priority.
The time-intensive operations in Swfdec can be divided into two parts:
1) actually progressing to the next frame and executing all the
required actions and 2) rendering the resulting image. If given the
choice I'd like to skip (at least some) redraws to keep up with the
suggested frame rate. However, I don't want to skip redraws that are
introduced by user interaction or other X events. So, I want to order
the priorities 1 > 2 > 3a (user-introduced) > 4 > 3b
(Flash-introduced).
So far this works fine, here's the caveat: If a partial repaint
happens, I need a consistent image. So if I handle an expose event for
a partial redraw, I need to either repaint the old image or update all
changes (including the Flash-introduced ones). But neither Gtk nor Gdk
give me a way to tell it "include these changed regions iff you
schedule an expose event, but don't schedule an expose event just for
these changes"). Is there a suggested way to solve this problem?
Here's the ideas I came up with to solve it, but about which I'm not
sure how much I like them:
1) Keep a pixmap of the current image. This causes extra memory to be
in use. It also makes double buffering inside Gtk useless.
2) Use gdk_window_freeze_updates and schedule redraws myself with the
lower priority. (This is equivalent to omitting step 3a above). It has
the disadvantage of not doing updates immediately when a previously
obscured region becomes visible again.
3) Turn off the widget's double buffering and doing the
gdk_window_begin_paint_region() call manually after union'ing it with
the to-be invalidated region. This is the solution I like best so far
and will probably implement unless someone comes up with a better one.
Cheers,
Benjamin
More information about the Swfdec
mailing list