サイズ: 3591
コメント:
|
← 2013-03-07 16:57:27時点のリビジョン6 ⇥
サイズ: 4461
コメント: 少し正確に
|
削除された箇所はこのように表示されます。 | 追加された箇所はこのように表示されます。 |
行 8: | 行 8: |
* 後発だがより低レイヤー | * 後発だがより低レイヤー。ほぼプロトコルと1対1対応 * Xlibには複数のリクエストを送る関数がある |
行 10: | 行 11: |
* 同期/非同期の違い * Xlib: リクエストに対するレスポンスは同期(リクエストを行う関数の戻り値)、エラー通知は非同期(エラーハンドラ) * XCB: リクエストに対して、レスポンスもエラー通知も非同期 |
* 同期/非同期の自由度 * Xlib: 同期/非同期が選べない * レスポンスを得るものについては、リクエストの送信とレスポンスの取得が不可分 * リクエストだけのものでエラーが発生した場合、事前に設定したエラーハンドラが呼ばれる * XCB: 同期/非同期が選べる |
行 15: | 行 18: |
* 複数のリクエストを送って複数のレスポンスを得る場合、先にリクエストを全部送ってからレスポンスを取得すると効率が良い * エラー取得のタイミングを自分で制御できる * リクエストキューをflushするタイミングをある程度制御できる。逆に言えば、必要な場面でflushを忘れるとリクエストが実行されない |
|
行 70: | 行 76: |
/* この~0x80は何なのだろう */ | /* SendEventリクエストによって送信されたイベントの場合、response_typeのMSBが1になる そのままではイベントの種類を正しく判別できないので~0x80でマスクしてMSBを除去する 詳しくはxcb_event.hを参照*/ |
XCBの基本
XCBのチュートリアルを見ながら写経。
Xlibと何が違うのか
今のところの理解。
- Xlibよりダイレクトにプロトコルを操作する
- 後発だがより低レイヤー。ほぼプロトコルと1対1対応
- Xlibには複数のリクエストを送る関数がある
- ライブラリの実装自体が仕様(xcb-proto)から自動生成されているらしい
- 後発だがより低レイヤー。ほぼプロトコルと1対1対応
- 同期/非同期の自由度
- Xlib: 同期/非同期が選べない
- レスポンスを得るものについては、リクエストの送信とレスポンスの取得が不可分
- リクエストだけのものでエラーが発生した場合、事前に設定したエラーハンドラが呼ばれる
- XCB: 同期/非同期が選べる
- リクエストを投げる際に関数の戻り値としてcookieを得る
- cookieを使ってレスポンスあるいはエラーを得る
- 複数のリクエストを送って複数のレスポンスを得る場合、先にリクエストを全部送ってからレスポンスを取得すると効率が良い
- エラー取得のタイミングを自分で制御できる
- リクエストキューをflushするタイミングをある程度制御できる。逆に言えば、必要な場面でflushを忘れるとリクエストが実行されない
- Xlib: 同期/非同期が選べない
- 適切に使えばXlibよりかなり速い
ここにある500個のアトム値を作るサンプルだと、手元の環境ではXCBの方が10から20倍速かった
- そもそも今のXlibはXCBの上に互換レイヤーとして実装されているとかいないとか
矩形を描画するだけの何の面白みもないプログラム
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <xcb/xcb.h>
4
5 xcb_connection_t *conn;
6 xcb_screen_t *screen;
7 xcb_window_t win;
8 xcb_gcontext_t gc;
9
10 int main(void)
11 {
12 int screen_num, i;
13 xcb_screen_iterator_t iter;
14 uint32_t mask, values[10];
15
16 conn = xcb_connect(NULL, &screen_num);
17
18 /* get screen information */
19 iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
20 for (i = 0; i < screen_num; ++i)
21 xcb_screen_next(&iter);
22 screen = iter.data;
23 puts("screen information:");
24 printf("%dx%d, root = %x\n", screen->width_in_pixels,
25 screen->height_in_pixels, screen->root);
26
27 /* create gc */
28 gc = xcb_generate_id(conn);
29 mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
30 values[0] = screen->black_pixel;
31 values[1] = 0;
32 xcb_create_gc(conn, gc, screen->root, mask, values);
33
34 /* create window */
35 win = xcb_generate_id(conn);
36 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
37 values[0] = screen->white_pixel;
38 values[1] = XCB_EVENT_MASK_EXPOSURE;
39 xcb_create_window(conn, XCB_COPY_FROM_PARENT,
40 win, screen->root, 0, 0, 200, 100, 1,
41 XCB_WINDOW_CLASS_INPUT_OUTPUT,
42 screen->root_visual, mask, values);
43
44 /* show window */
45 xcb_map_window(conn, win);
46 xcb_flush(conn);
47
48 xcb_generic_event_t *event;
49 while (event = xcb_wait_for_event(conn)) {
50 /* SendEventリクエストによって送信されたイベントの場合、response_typeのMSBが1になる
51 そのままではイベントの種類を正しく判別できないので~0x80でマスクしてMSBを除去する
52 詳しくはxcb_event.hを参照*/
53 switch (event->response_type & ~0x80) {
54 case XCB_EXPOSE:
55 xcb_poly_rectangle(conn, win, gc, 1,
56 &(xcb_rectangle_t){ 10, 10, 100, 50 }); /* C99の複合リテラル */
57 /* どうやらXCBでもリクエストはバッファリングされるらしい
58 この場合特にバッファをフラッシュする要因が無いようなので、
59 明示的にxcb_flushしないとリクエストがサーバに送られない = 描画されない */
60 xcb_flush(conn);
61 break;
62 default:
63 break;
64 }
65 free(event);
66 }
67 xcb_disconnect(conn);
68 return 0;
69 }
ウィンドウやGCのためのXIDは先にxcb_generate_idによって自分で作る
valuesはただの配列なので値の順序が重要(maskの値の小さい順に並べる)