Multithreaded rendering with Cairo

NOTE: if someone need English translation of this entry, I’ll do that with pleasure. If you need, please send me an E-mail.

cairo のドキュメンテーションというのは不思議なほど少なくて、API doc を隅から隅まで読んだ上で、いろいろ試したり想像をふくらませたりして遊んでるわけだが、このたび一念発起して、ずっと開発しているプログラムの、cairo を使ったレンダリングを並列化することにした。自分が dual core なプロセッサのマシンを使っているのに、書いているプログラムが single threaded だなんて、かっこ悪いからな。

基本的なやり方としては、メインの画像の一部を別のスレッドでレンダリングしてはめ込む、もしくは alpha channel を使って上に重ねるわけだが、どちらもやり方はほとんど同じだと思う。まず最初に、スレッドの数だけの surface と cairo drawing context を作る。このとき、surface type はメインの画像のものと同じにするが、surface content は color with alpha にしておくのが大事だと思う。

メインの cairo_t を cr とすると、

cairo_surface_t* surface;
cairo_surface_t* surface_p[10];
cairo_t* cr_p[10];
// create surfaces
surface = cairo_get_target(cr);
for(int i=0; i<10; i++){
surface_p[i] = cairo_surface_create_similar(surface,
CAIRO_CONTENT_COLOR_ALPHA,
WIDTH, HEIGHT);
cr_p[i] = cairo_create(surface_p[i]);
}

こんな感じで、surface と cairo context をたくさん作って、あとはそれぞれの context の上にじゃんじゃか絵を描けばよい。

さて、問題はこれをはめ込むときだ。仕掛けとしては、さきほどたくさん作った surface から cairo_pattern_create_for_surface() で pattern を作り、それを cairo_set_source() で指定した上で cairo_rectangle(); cairo_fill() とかすればよいのだが、重要なのは、cairo_pattern を使う場合、pattern は rectangle などの位置に関係なく、必ず(0, 0) を基準にして展開される ということである。したがって、rectangle の位置に pattern の位置が合うように、transformation matrix を指定してやらねばならない。

cairo_pattern_t* pattern;
for(int i=0; i<10; i++){
cairo_matrix_t m;
pattern = cairo_pattern_create_for_surface(surface_p[i]);
cairo_matrix_init_identity(&m);
m.x0 = -XPOS;  // -XPOS, but not XPOS !
m.y0 = -YPOS;  // -YPOS, but not YPOS!
cairo_pattern_set_matrix(pattern, &m);
cairo_set_source(cr, pattern);
cairo_rectangle(cr, XPOS, YPOS, WIDTH, HEIGHT);
cairo_fill(cr);
cairo_pattern_destroy(pattern);
cairo_surface_destroy(surface_p[i]);
cairo_destroy(cr_p[i]);
}

とまあ、こんな感じ。GTK とか PDF で試した感じでは、うまくいっている。

今日の自転車

4000km milestone は昨日だった模様。
今日は絶好調だった。往路は多摩川サイクリング道路を、多摩沿線道路をロードで走っている人をペースメーカーにして 35km/h くらいで飛ばす。サイクリング道路は信号はないけど、舗装が荒れてたり、前方不注意な人たちがいたりで、意外に走りづらいので、条件は五分。大学までは平均で 27.2km/h 。
復路は日吉から田園調布まで出て、環八通りから世田谷通り。東横線を越えたちょっと先までが上りなのだが、アウターでワシワシとペダルを回し、東横線を越えるところでオールアウト。つらかったが、その先の下りで回復。世田谷通りに入ったところで平均速度が 28.0km/h になり、成城からの下りで 28.3km/h くらいまで上がった。いやもう、すっげえ楽しかった!!
やっぱりあれだ、ご飯食べてしばらくしてから乗ると調子がいい感じ。
左のペダルを踏み込むとパキパキ音がするのだが、どうもボトルケージの取り付け部っぽい。ボトルケージの台座には、携帯ポンプの台座も噛ませてあり、そのあたりか。明日注油してみよう。
新しく買ったシマノのシューズは、前のパールイズミの vagabond というモデルに比べると、ソールの剛性感・アッパーのホールド感ともに段違い。ただ、ちょっと堅すぎるかな。靴底の形はシマノの方が扁平で、僕の足の形には合っていない気がするので、これはそのうちちゃんとしたインソールを買わないと、足を傷めるかも。
37.47km @ 28.2km/h (1h19m39s) odo 4041.3km

接種

インフルエンザの予防接種うけた。
で、やっぱりウイルスを注入するわけで、夜はすこし熱っぽくてぼーっとなった。注射したところもちょっと腫れたし。
起きたら、腫れ以外はすっきりしてたので、大丈夫。
今日はチャリで go.

敗走

買い物にいった帰りに甲州街道走ってたら、ロードに抜かれた。
ナルシマのジャージをびしっと着た人で、車種はわからなかったが、形状と制動音から察するにカーボンフレームにカーボンホイールであり、そうとうやる気だ。
で、カウンターアタックを決めようと思ったんだが、相手がかなり速くて全然ダメだった。俺、お茶とか衣類とか買った帰りで荷物もあったし、なによりインフルエンザの予防接種直後だからな (笑)。
そうそう、あたらしいシューズはかなり剛性が高くていい感じだ。ギア掛けてダンシングで加速するときとか、最高です。

Leopard の X とか

MacOS X 10.5 の X11 だが、なんか、dual display とかにした状態で、別のディスプレイの方にウィンドウを移動したりすると、すごくおかしなことになっている気がする…
今日は研究室でセミナがあり、いつものようにそうしようと思ったのだが、結局プロジェクタと MacBook のディスプレイをミラーリングすることになった。
あと、最近経験した不具合としては、
– syslogd が大暴走して電車の中で電池がなくなりそうになった
– /usr/sbin/DirectoryService が大暴走して名前が引けなくなった
– iDisk の同期がうまくいかなかったのか、~/Library/FileSync が 100GB くらいになった (笑)
などなど。やっぱりまだ、10.5 に移行するにはちょっと早いかもしれんね。
困ったちゃん。でも、やっぱりけっこうイケてるので、いまさら戻れないし。

root

最近猛烈に root 仕事の負荷が高く、
終わったと思っても次から次へと問題が発生する。
やってられん。ていうか、俺の仕事じゃないのに。

44

靴のサイズは 44 だ。欧州の規格で。
で、先日レーサーシューズが壊れてしまって、このままでは自転車に乗るのが近所だけに限定されてしまうので困ったぜ、と思い、午後仕事が終わってから自転車屋を2軒ほど回ってみた。
41 とかのサイズならどこにでもあるんだが。そして、みんなそれくらいらしい。
いま履いているのはパールイズミの 43。その前はずっとシマノの 44。
シマノの 43 は、入らなくもないんだが、ちょっときつい。
SIDI の 43 なんか、幅が狭すぎて全然ムリ。
職場で履いている Birkenstock のサンダルは、実は 42 ですが、けっこうぎりぎりです。まあ、サンダルだからいいようなもので。
で、44 はシマノの SH-R151L というのしか手に入らなかった。いままでで買ったレーサーシューズでは一番高いな。
ほんとは、バックルのついてるやつがほしかったんだが、いままでと同じ3本ストラップになってしまった。まあ、ゴール前でバックル締め付けてスプリント、なんていうことするわけじゃないので、これで充分なんだけどね。慣れてるし。
ていうか、カーボンソールですよ。むふ。
クリートの取り付けが終わったので、片足だけつっこんでペダルに入れてみた。
フィット感がたまりません。明日走るのが楽しみだ!