VNC Server for SigmarionIII(VGA chip=IMAGEON4200, OS=WindowsCE)
Based on WinCEVNCServer(cvs.sourceforge.net:/cvsroot/wincevncsvr)
【VNC server for SigmarionIII】
□ ... TODO
■ ... DONE
■ RAW encode protocol のみサポート
Tight encoding などのプロトコル対応を検討したが,圧縮 encoding 処理
は負荷が高いためサポートしない方針とした.
■ (IMAGEON4200)HardwareBitBlitを利用した差分検出
800 * 480 * 16bpp = 768000 bytes (750K bytes)
= 0x0000.0000 ~ 0x000b.b800
windows の場合はupdateハンドラを用いて部分的な差分を容易に検出できるが,
WinCEではハンドラを設定できないため,全画面をバッファに退避させておき,
現在の画面と比較して更新部分を scan する.
AhiSurfAlloc(Ctx*, out Surf**, int size[2], int type, int mode)
0) fore ground surface 取得
AhiDispSurfGet(ctx, &surf_fg);
1) back groundサーフェスを作成
/*
* type: 5 ...16bpp
* mode: 0x20 ...外部メモリ
*/
int size[2]= {SCREEN_X, SCREEN_Y};
AhiSurfAlloc(ctx, &surf_bg, size, 5, 0x20);
AhiSurfAlloc(ctx, &surf_diff, size, 5, 0x20);
WORD *bmp_bg; /* WORD [SCREEN_X * SCREEN_Y] */
WORD *bmp_diff; /* WORD [SCREEN_X * SCREEN_Y] */
AhiSurfLock(ctx, surf_bg, bmp_bg, 0);
AhiSurfLock(ctx, surf_diff, bmp_diff, 0);
2) ROP=normal で surf_fg を surf_diff にコピー
int pos_base[2]= {0,0};
int rect_full_screen[4]= {0, 0, SCREEN_X, SCREEN_Y};
AhiDrawRopSet(ctx, 0xcccc);
AhiDrawSurfSrcSet(ctx, surf_fg, 0);
AhiDrawSurfDstSet(ctx, surf_diff, 0);
AhiDrawBitBlt(ctx, rect_full_screen, pos_base);
----------- ↑ 初期化 ↑ ------------
----------- ↓ ループ ↓ ------------
3) ROP=normal で surf_fg を surf_bg にコピー
AhiDrawRopSet(ctx, 0xcccc);
AhiDrawSurfSrcSet(ctx, surf_fg, 0);
AhiDrawSurfDstSet(ctx, surf_bg, 0);
AhiDrawBitBlt(ctx, rect_full_screen, pos_base);
4) ROP=XOR で surf_bg を surf_diff にコピー
AhiDrawRopSet(ctx, 0x6666);
AhiDrawSurfSrcSet(ctx, surf_bg, 0);
AhiDrawSurfDstSet(ctx, surf_diff, 0);
AhiDrawBitBlt(ctx, rect_full_screen, pos_base);
5) ブロック単位で差分検出&検出ブロック送信
if (bmp_diff[x + SCREEN_X * y] != 0) {
bmp_bg[] からブロックデータを作成して送信
}
6) surf_bg と surf_diff のポインタ値を入れ替え
WORD *bmp_tmp = bmp_bg;
bmp_bg = bmp_diff;
bmp_diff = bmp_tmp;
struct Surf* surf_tmp = surf_bg;
surf_bg = surf_diff;
surf_diff = surf_tmp;
3,4,5,6) をループ
----------- ↑ ループ ↑------------
----------- ↓ 後始末 ↓ ------------
7) 資源の解放
AhiSurfUnlock(ctx, surf_bg); bmp_bg = NULL;
AhiSurfUnlock(ctx, surf_diff); bmp_diff = NULL;
AhiSurfFree(ctx, surf_bg);
AhiSurfFree(ctx, surf_diff);
AhiDevClose(ctx);
■ タスクバー常駐
■ Tight encode のブロックデータ圧縮アルゴリズムを検討
- encode処理が重いので却下
- vncTightEncode の矩形送信シーケンス↓
vncClient.cpp: vncClient::SendRectangle(RECT &rect)
vncClient.cpp: UINT bytes = m_buffer->TranslateRect(rect, m_socket);
vncBuffer.cpp: vncBuffer::TranslateRect(const RECT &rect, VSocket *outConn)
vncBuffer.cpp: return m_encoder->EncodeRect(m_backbuff, outConn, m_clientbuff, rect);
vncEncoder.cpp: vncEncoder::EncodeRect(BYTE *source, BYTE *dest, const RECT &rect)
vncEncodeTight.cpp: vncEncodeTight::EncodeRect(BYTE *source, VSocket *outConn, BYTE *dest,
vncClient.cpp: m_socket->SendQueued((char *)(m_buffer->GetClientBuffer()), bytes);
□ 全画面縮小
Sig3側で予め縮小した画面サイズで処理,転送ボトルネックを下げる.
- IMAGEON4200 の拡大縮小コピー機能 AhiDrawStretchBlt()
□ (BUG) key map 修正
□ (調査) PortForwarder でパケット圧縮した場合の転送レート向上度合.
□ 選択した一部の領域を全画面としてviewerへ転送
□ 負荷に応じた sleep() 期間の動的変更
□ setsockopt() にて send buffer size 調整
□ IMAGEON4200内部メモリに Surface を用意して高速化
速度計測をしていないが,現状メリットが少ない.
- 内部メモリには全画面分を退避する事は出来ないので,全画面を対象にする場合
にはメインメモリとのコピーは避けられない.
- 全て内部メモリで賄う場合の画面サイズは 400x200x16bpp
AhiSurfAlloc() mode=0x40 指定時の内部メモリサイズは 320KB → 400x400x16bpp
差分検出には 2 枚のSurface(back,diff)が必要なので最大画面サイズは 400x200x16bpp
- デメリット. リソース(IMAGEON4200内部メモリ)を占有してしまう.
- メモリアクセススピードの測定. 要測定方法調査