今夜も Wine で乾杯! - 21本目 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
Linux上でWindowsのアプリを動作させるソフトウェア
Wineに関する情報交換スレ。
前スレ
今夜も Wine で乾杯! - 20本目
https://mao.2ch.net/test/read.cgi/linux/1455088008/
Wine本家
http://www.winehq.org/
http://wiki.winehq.org/
動作報告Wikiや過去ログなど
http://www.2chlinux.org/index.php?FrontPage
ここにパッチをうpするときはgzipやbzip2で圧縮した上で
base64などでエンコードしてください。おながいします。
動作報告は>>2のテンプレ使用を推奨。 ~$ wine --version
wine-1.8.7 (Debian 1.8.7-2)
~$ winetricks --version
20170101
で,Internet Expolorer 8 のインストールがWebページの404エラーにより失敗しました。
https://web.archive.org/web/http://download.microsoft.com/download/WindowsInstaller/Install/2.0/NT45/EN-US/InstMsiW.exe
どなたか ie8 が配布されているサイトに心当たりはないでしょうか。
欲を言えば winetricks から操作できると嬉しいです。 なんかwine-stable入れなおしたらフォントがちゃんとWindowsみたいにアンチエイリアスなしでビットマップフォント描画するようになってて違和感
以前
https://i.imgur.com/33J6RXR.png
現在
https://i.imgur.com/S4LWJZS.png >>329
へ〜Jane Styleだとこうなるのか
ちょっと試してみるわ wine3.0にしたらadobe airがインストールできなくなった
air28だけでなく27も26もだめ
しばらく様子をみるしかないか qtもインストール出来なくなったね(´・ω・`)
未実装の関数がどうとか出てくる(´・ω・`) qtもなんだ
office2007とかすごく快適に使えてるからとりあえずはいいんだけど
郵便局のハガキデザインキットで暑中見舞い作りたいからそれまでにはなんとかしてほしいわ Developmentだからなあ
基本Stableを第一に考えてるので3.0が優先かな
まずは他に方法がないかいろいろ探してみようと思う >>331
自己解決
adobe airをwinetricksから試しにインストールしてみようと思ったら、ついこの前までadobe air2.0xと表記されてたものが今はadobe airとだけの表記に変わってた
これをインストールすると郵便局のハガキデザインキット2018もちゃんとインストールできた
wine uninstallerで見てみるとadobe airはちゃんと最新版28.0.0.127になってる
何のことはない、adobeのサイトからではなくwinetricksからだったらインストールできたというオチでした
https://i.imgur.com/21NbqT3.png >>331
自己解決
adobe airをwinetricksから試しにインストールしてみようと思ったら、ついこの前までadobe air2.0xと表記されてたものが今はadobe airとだけの表記に変わってた
これをインストールすると郵便局のハガキデザインキット2018もちゃんとインストールできた
wine uninstallerで見てみるとadobe airはちゃんと最新版28.0.0.127になってる
何のことはない、adobeのサイトからではなくwinetricksからだったらインストールできたというオチでした
https://i.imgur.com/21NbqT3.png >>331
自己解決
adobe airをwinetricksから試しにインストールしてみようと思ったら、ついこの前までadobe air2.0xと表記されてたものが今はadobe airとだけの表記に変わってた
これをインストールすると郵便局のハガキデザインキット2018もちゃんとインストールできた
wine uninstallerで見てみるとadobe airはちゃんと最新版28.0.0.127になってる
何のことはない、adobeのサイトからではなくwinetricksからだったらインストールできたというオチでした
https://i.imgur.com/21NbqT3.png お恥ずかしい
書き込みエラーが出たので試しにプロキシの設定の書き込みの方にもチェックを入れてみたところ、いきなり3回書き込みになってしまいました >>347
男子コリア人や男子中国人、男子シベリア人ですか 若いころは、JSがまさかここまで人気になるとは思わなかったな。
Javaに似せただけがとりえのスクリプトだと思ってたのに。 いや全然Javaに似てなくないか
JSってかなり変わった言語だと思うけど ごめん、名前の話ね。
JSリリース当初は、まさに全然違うのになぜLiveScriptからJavaScriptに変えたんだろう、と思ったんで。 >>353
/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄\
| おまわりさんコイツです! |
\_ ________/
∨ ___
,r'つ@=,r'
.| (-_- )
(・ω・´)、/~У ̄|゙i
゚こ、 つ |=◎=∪
しー-J (_(__) >>350
大半が同じ感想のはず。
ajaxの手法が公開されてから一気に沸騰した。 The Wine development release 3.1 is now available.
What's new in this release (see below for details):
- Kerberos authentication support.
- Window class redirection for Common Controls 6.
- Support for X11 ARGB visuals.
- DOSBox required for running DOS executables.
- Various bug fixes. wine-staging2.21からwine-stable3.0にしたら
負荷とメモリ消費が素晴らしく改善されたから
開発版に手を出しかねてる
3.0で改善されたのか、stagingのものが足を引っ張ってたのか判別つかなくて 3.4のときは起動すらしなかったのにな
4.0になったら快調すぎる 結局のところwinehq-stableとwine-stableの差は何なのさ winehq stableが公式サイトで公開されてるやつでwine stableは各ディストリから配布されてるやつだと思ってたけど違うのかな wine-3.1-arm.apk
ExaGearより動くかなと期待して入れたんだけど、プログラムが一つも動かない…
まだ見てくれだけの未完成品ってこと? あー Windows RT ARMのソフトしか動かないのかこれ >>371
こいつMac関連のスレ狙ってる?別にそんな事ないのかな crossoverのベースになっているwineのバージョンってどこから調べたらいいの?
もう3.0ベースになってるのかな ちがったかな
$ /opt/cxoffice/bin/wineserver --version
wine-2.8-8251-g8a457d1 ubuntu studio 16.04LTS にwineを入れて、
JaneStyle を使える様にはなった。
書き込みテスト。 >>368
まじかよ、Elonaさえ動けばいいのに。 ARM機とかスマホしか持ってないわ
これから増えるんかね PS VitaもARMだしSwitchもARMだな RTでコケて痛い目にあったからそれはないと思う。
ARMじゃない別のアーキテクチャで出す可能性はあるかも・・・
そしてまたコケるw >>385
いや出るから
HPとASUSがsnapdragon搭載Windows端末を発表済で春に発売予定 売れるとは限らないんだがなぁ
x86exeが何となくでも動くだけでいいのにな ちょっと調べてから否定しようよ
まあいいんだけどさ 古いけど、Ubuntu12.01 への Wine3.0のインストールに成功した。
git のソースから、./configure
途中、Font関連のファイルが見つからないエラーが出たので、
そのFontの「dev版」をapt-getでインストール。
その他、いくつかエラーが出るので、インストールしたりする。
その後、make, make install。
でインストールには成功するが、今まで動いていたWinアプリを起動してみると
日本語で文字化けしてる。wintricks font や regedit などをいじってみたが、
ダメだった。しかし、apt-get remove wineとしたあと、再度、
apt-get install wineとすると、なぜか、すぐに成功した。
wine --versionとすると、なぜか、3.1のままだった。
不思議な事に、文字化けはすっきり解決した状態で、Ver 3.1のWineが動いているらしい。
実際、Windowsとの互換性は明らかに向上した。 Wzエディタで、検索やGrepのダイアログのStatic Textの表示が途切れてしまう
不具合があったのが、Wine3.0では修正されている。これは使える。 透明色と MDI Window を組み合わせた自作WindowsアプリをWineで動くように修正中。
MDI Child Widnow のタイトルバーをドラッグすると遅くなるので原因を調査していた。
PreTranslateMessage() にくるメッセージを、自前でWindowに表示していたところ、
システム全体が実質的にハングアップした。マウスは動くが、タスクバーも反応しない。
ちなみに、透明色とMDI Windowの組み合わせが必ず遅くなるわけではない事は、
単純なテストプログラムを作って分かっている。ではなぜ、このプログラムに限っては
遅くなるのかが分からないので調査中だった。 The Wine development release 3.2 is now available.
What's new in this release (see below for details):
- Separate implementation of USER controls for ComCtl32 v6.
- Multisample texture support in Direct3D.
- Support for HID gamepads.
- More event support in MSHTML.
- Obsolete DOS code removed.
- Various bug fixes. Wineは、Desktopの直接の子であるような、Win32における「OVERLAPED WINDOW」
的な物しか、XWindow の Window を作らないのだろうか??
Wineのソースをダウンロードして、FIXME(WARNでもいいはずだけど)で実行を調べてみた。
でも、良く分からない。ビルドとmake installに時間がかかるため、大変。
本当はもっと実験したいんだけど、時間的に難しくなる。
ソースを見ると、HWNDの親が Desktopの場合にだけ、XCreateWindowしているように
見える。これが、透明ウィンドウが遅くなる理由かもしれない。LinuxのNativeなWindowの
場合、実験した限り透明にしても速度が余り変わらない。でも、Wineがもし、自前で透明処理
をやっているとなれば遅くなるのも頷けるが。
1つのソースしか修正してないのに、ビルドが始まるまでに数十秒かかる。make installに
また数十秒。それに、wineserver -k などにも時間がかかるし。なんか、30年前のビルド環境
みたいだ。 >>397
今回に関しては、以下を読んで、git でやってます :
https://wiki.winehq.org/Git_Wine_Tutoria
home directory (~) にて、
$ git clone git://source.winehq.org/git/wine.git [ret]
とすると、wine ディレクトリが作成されるので、
$ cd wine
とします。そこで、
$ git config remote.origin.url [ret]
と入れて
git://source.winehq.org/git/wine.gi
と出れば、大体 DL 成功です。
~/wine/ にソースが DL されており、dlls に Win32 の DLL 群の実装があります。
例えば、user32 などのフォルダがあります。~/wine/server に wine の中枢の
プログラムが入っています。CreateWindow などは、dlls の方にありますが、
それを XWindowCreate に橋渡しするのは、server の方です。
オンラインで見たいなら、
https://source.winehq.org/git/wine.git/tree/HEAD:/dlls/user32
の win.c に CreateWindow 系のソースが入っており、
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/user32/win.c
で見られます。win.c の右の「raw」のボタンを押すと、ローカルの Wz エディタ
などでも見られます。 5ch からのアクセスは禁止されているらしいので、アドレスバーに上記の URL を
コピーしてアクセスしてください。
なお、make が遅い件は、make -j 4 などとして、マルチコア動作するとだいぶ良くなりました。
ただし、その場合、make にバグがあるので精密な神経の持ち主には、ストレスがたまります。 動きをトレースしたい場合、TRACE はデフォルトではメッセージが出ず、使い方を調べて
ないので、
FIXME( "Yamada Taro, CreateWindowEx, hWND=%08X", hWND );
みたいにやってます。 makeしたい人は、~/wine にて、
$ ./confiugre
$ make -j 4 2>build.log
$ make -j 4 install 2>inst.log
$ wineserver -k
で行けます。ここで、wz エディタを起動してみます。文字化けするようでしたら、
$ apt-get remove wine
$ apt-get install wine
で直ると思います。これは、一度やれば Ok のようです。 call set_window_pos()
--> wine/dlls/user32/winpos.c
--> X11DRV_WindowPosChanging()
--> X11DRV_create_win_data()
--> dlls/winex11.drv/window.c :
static void create_whole_window( struct x11drv_win_data *data )
--->
data->whole_window = XCreateWindow(
data->display, root_window, pos.x, pos.y,
cx, cy, 0, data->vis.depth, InputOutput,
data->vis.visual, mask, &attr );
という流れのようです。 以下を見ると、親が、DesktopWindow の時のみ、create_whole_window() が呼び出されている
らしいことが分かります。
static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const RECT *window_rect,
const RECT *client_rect ) {
Display *display;
struct x11drv_win_data *data;
HWND parent;
if (!(parent = GetAncestor( hwnd, GA_PARENT ))) return NULL; /* desktop */
/* don't create win data for HWND_MESSAGE windows */
if (parent != GetDesktopWindow() && !GetAncestor( parent, GA_PARENT )) return NULL;
if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) return NULL;
display = thread_init_display();
init_clip_window(); /* make sure the clip window is initialized in this thread */
if (!(data = alloc_win_data( display, hwnd ))) return NULL;
data->whole_rect = data->window_rect = *window_rect;
data->client_rect = *client_rect;
if (parent == GetDesktopWindow()){
create_whole_window( data );
TRACE( "win %p/%lx window %s whole %s client %s\n",
hwnd, data->whole_window, wine_dbgstr_rect( &data->window_rect ),
wine_dbgstr_rect( &data->whole_rect ), wine_dbgstr_rect( &data->client_rect ));
}
return data;
} >>402 の訂正:
CreateWindowExW()
--->
WIN_CreateWindowEx()
call set_window_pos()
--> wine/dlls/user32/winpos.c
--> X11DRV_WindowPosChanging()
--> X11DRV_create_win_data()
--> dlls/winex11.drv/window.c :
static void create_whole_window( struct x11drv_win_data *data )
--->
data->whole_window = XCreateWindow(
data->display, root_window, pos.x, pos.y,
cx, cy, 0, data->vis.depth, InputOutput,
data->vis.visual, mask, &attr ); ちなみに、
1. ~/.wine
2. ~/wine
は別物です。1は、binary をインストールした際に出来るデフォルトのフォルダ
ですよね。2. は、git からソースを持ってきた時にできるディレクトリです。
まずは、バイナリをインストールして動作してから、ソースを持ってきてください。 半透明化はWin32API側でどうやっているの? Linuxネイティブなアプリでは?
SetLayeredWindowAttributesであれば、user32.dllからUSER_Driverを介してwinex11.drvが呼ばれて、
window.c内のsync_window_opacityで_NET_WM_WINDOW_OPACITYにα値を設定している様子が見て取れる
ttps://github.com/wine-mirror/wine/blob/wine-3.2/dlls/winex11.drv/window.c#L435
TRACEで表示しているメッセージを確認するには環境変数WINEDEBUGを使って、
WINEDEBUG=win,x11 みたいにカンマ区切りで指定する。細かくは
ttps://wiki.winehq.org/Wine_Developer%27s_Guide/Debug_Logging に書いてある。
あとは、dlls配下の各ディレクトリでもmake && sudo make instlallできるので
特定のDLLファイルしか変更しないのであれば、この方法でビルド時間を短縮できるぞ。 デバッグ大変だな。めんどくさそう。
仕事じゃないと俺はやらないだろうな。 自分はimm32関連(日本語入力)APIを修正しようとeclipceでコンパイル環境作ったはいいけど
ネイティブのウィンドウマネージャ関連の知識不足でソースの意味がわからず寝かせてある・・・ >>406
Linux Nativeアプリの場合、32BIT COLOR にすると、A,R,G,B の 4つの値を
ドットの「色」として指定できます。Aがα値です。このようなことは、Windows
では出来ないと思います。Windowsの場合、CreateWindowExのdwExStyle に
WS_EX_LAYEREDを指定すると透明、半透明が扱えるようになります。
1.完全に「透明になる色」を24BIT値で1色指定できます。この色で描いたドットは、
デスクトップまで透けて見えるようになります。見た目だけではなく、Windowメッ
セージも下のWindowに伝達されてしまうことになりますが。
2.ドットごとではなく、Window全体のα値を1つ(1BYTE)だけ指定できます。
ドットごとでは無いので、全体的に透明度が決まってしまいます。
1と2は完全に別の概念です。
LinuxのARGB値は、ドット毎に指定できるので、Windowsの機能を包含していると
言えます。逆に Windowsでは、同じ事は出来ないはずです。 /wine/dlls/winex11.drv/x11drv.h
に次のような構造体があり、この whole_window というのが大事らしい:
/* x11drv private window data */
struct x11drv_win_data {
Display *display; /* display connection for the thread owning the window */
XVisualInfo vis; /* X visual used by this window */
Colormap colormap; /* colormap if non-default visual */
HWND hwnd; /* hwnd that this private data belongs to */
Window whole_window; /* X window for the complete window */
Window client_window; /* X window for the client area */
RECT window_rect; /* USER window rectangle relative to parent */
RECT whole_rect; /* X window rectangle for the whole window relative to parent */
RECT client_rect; /* client area relative to parent */
XIC xic; /* X input context */
BOOL managed : 1; /* is window managed? */
BOOL mapped : 1; /* is window mapped? (in either normal or iconic state) */
BOOL iconic : 1; /* is window in iconic state? */
BOOL embedded : 1; /* is window an XEMBED client? */
BOOL shaped : 1; /* is window using a custom region shape? */
BOOL layered : 1; /* is window layered and with valid attributes? */
BOOL use_alpha : 1; /* does window use an alpha channel? */
int wm_state; /* current value of the WM_STATE property */
DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */
Window embedder; /* window id of embedder */
unsigned long configure_serial; /* serial number of last configure request */
struct window_surface *surface;
Pixmap icon_pixmap;
Pixmap icon_mask;
unsigned long *icon_bits;
unsigned int icon_size;
}; >>406
後半の二つ。自分に取っては、かなり貴重な情報です。助かります。 >>406
XWindow で透明化。これはやってみて実際に出来ました:
https://stackoverflow.com/questions/39906128/
how-to-create-semi-transparent-white-window-in-xlib
子ウィンドウを入れてみても、ちゃんと出来ました。
ただし、子ウィンドウには、Win32のような、タイトルバーは付ききませんでした。
XWindow に詳しい人によれば、XWindow の Window Manager は、
Win32 の MDI のような事は、サポートしていないらしいです。絶対か
どうかは分かりませんが。
実験してみると、子ウィンドウも、親ウィンドウも、ABI で、XMoveWindow
でスムーズに動かせました。
ただし、Wineの場合、子ウィンドウに直線や文字が書かれていて、かつ、背景が透明な場合、
スムーズには動かせません。 Win32APIだけじゃなく、X Windowについても知っておかないといけないのか
面倒臭っ・・・
普段使ってるだけでずいぶん楽してたんだな。 面白そうだけど時間ねえな……
>>410を見る限りだとuse_alphaは持ってるけどAlpha値自体はもうX11の構造体にいれてるのかな?
まあ遅くなる理由とか検討つかんけど…… WINEにおいて、
1. MDIのCMDIChildWndのCViewのCLIENT領域全体(子ウィンドウの
中全体と言ってもよい) に >>409の1.の色を塗って、完全透明
にしている時は、CMDIChildWndのタイトルバー(子ウィンドウの
タイトルバー)をドラッグしても高速に動かせる。
2. 1のCViewの中に、pDC->LineTo()で直線を一本描いた状態にしてから
同じ事をしようとすると、とても遅くなる。
3. 2.は、直線の代わりに pDC->TextOut() で文字を描いても同様に遅く
なる。
4. 推定では、Wineは、Win32のCreateWindow系で、Parent Window が
Desktop 以外の場合、XWindow の Window を使わず、自前で
Parent Window の中に画像を合成して子Windowを模倣している。
5. 4.の様にしている理由は、推定だと Window Manager の種類による
挙動の違いに患わされずに安定して Emulation するためかも知れ
ない。
6. その結果、XWindow の ARGB 値による高速な透明処理を利用できな
くなり、低速になる。
7. しかし、なるべく低速にならないようにするため、少なくとも、
子ウィンドウの中全体が完全透明な場合については、対策が取ら
れており、高速にドラッグできるようになっている。
8. その結果、2, 3 のような条件の時のみ遅くなると推定される。 >>415
すまん、ウィンドウの半透明化処理(LWA_ALPHA)と勘違いしてた。
ウィンドウ領域内の特定色で書いた箇所を透過させる場合(LWA_COLORKEY)ね。
ソースを調べたら、WineではX11のShape Extensionを使ってウィンドウの形状を変更することで、
「見た目だけではなく、Windowメッセージも下のWindowに伝達すること」を実現しているようだ。
具体的にはupdate_surface_region()で1ピクセルごとにピクセル値を比較して、
XShapeCombineRectanglesに指定する矩形領域を作っている。
ttps://github.com/wine-mirror/wine/blob/2936f3f9bb9dc01c595498a821d6adb6775b62cc/dlls/winex11.drv/bitblt.c#L1616
415の2.,3.の条件だと遅くなるとすると、ピクセル値を比較する処理は1.と同じなので、
矩形が大量になったときに、X側で描画性能が低下するのではないかと思うぞ。
StackOverflowの記事はShape Extensionを使っていないので筋違いだ。 >>418
なるほど。
1つ質問です。
はっきりとは書いてなかったのですが、>>415の遅くなる条件であるところの 2,3 の場合
においても、CMainFrame、つまり、アプリケーション全体の Main の Window のタイトルバーを
ドラッグした場合は、遅くなりません。いたって高速にドラッグできます。
>>418 が正しいなら、どうして、X は、この場合だけは速く、CMDIChildWnd の場合だけは
遅く動作するのでしょうか??? ↓の構造体の dc_rect の矩形が子ウィンドウを模倣するために使われているかも知れません:
/* X physical device */
typedef struct {
struct gdi_physdev dev;
GC gc; /* X Window GC */
Drawable drawable;
RECT dc_rect; /* DC rectangle relative to drawable */
RECT *bounds; /* Graphics bounds */
HRGN region; /* Device region (visible region & clip region) */
X_PHYSPEN pen;
X_PHYSBRUSH brush;
int depth; /* bit depth of the DC */
ColorShifts *color_shifts; /* color shifts of the DC */
int exposures; /* count of graphics exposures operations */
} X11DRV_PDEVICE;
BOOL X11DRV_LineTo( PHYSDEV dev, INT x, INT y ) {
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
POINT pt[2];
GetCurrentPositionEx( dev->hdc, &pt[0] );
pt[1].x = x;
pt[1].y = y;
LPtoDP( dev->hdc, pt, 2 );
add_pen_device_bounds( physDev, pt, 2 );
if (X11DRV_SetupGCForPen( physDev ))
XDrawLine(gdi_display, physDev->drawable, physDev->gc,
physDev->dc_rect.left + pt[0].x, physDev->dc_rect.top + pt[0].y,
physDev->dc_rect.left + pt[1].x, physDev->dc_rect.top + pt[1].y );
return TRUE;
} /wine/dlls/user32/painting.c の中の、
// Set the visible region and X11 drawable for the DC associated to a given window.
static void update_visible_region( struct dce *dce )
の中に、
USER_Driver->pGetDC( dce->hdc, dce->hwnd, top_win, &win_rect, &top_rect, flags );
とあって、
void CDECL X11DRV_GetDC( HDC hdc, HWND hwnd, HWND top, const RECT *win_rect,
const RECT *top_rect, DWORD flags )
が呼び出される。引数に hwnd と top、win_rect と top_rect が対になっているらしいことに注意。
この関数の中で、x11drv_escape_set_drawable escape; の
escape.dc_rect に、win_rect の top_rect の (left, top) からの相対座標が入れられる。
そして、ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL );
と ExtEscape() が呼び出される。
escape = X11DRV_ESCAPE;
escape.code = X11DRV_SET_DRAWABLE;
in_data = &escape;
の状態で、
X11DRV_PDEVICE *physDev = get_x11drv_dev( dev );
const struct x11drv_escape_set_drawable *data = in_data;
physDev->dc_rect = data->dc_rect;
となる。physDev->dc_rect が、>>420 の dc_rect に他ならない。
つまり、HWND hwndのwin_rectの、HWND topの左上座標からの相対座標が、
physDev->dc_rect に入ることになると思われる。hwndの「最上位の親」が
topだとすると、topだけが XCreateWindow()された本物のWindowであって、
hwnd は 擬似Windowであるとして辻褄が合う。hwndへの描画は、
実は座標だけを修正して top の(本物の X )Window に書き込まれているだけ
かも知れない。 結論的には、Wine では、完全透明色が設定されている全ての LAYERED_WINDOW に
対して、Idle状態の時か、または、50(ms) 毎に、Windowアプリのメッセージループ
の中から自動的に、>>418 の update_surface_region() が呼び出されるようになっ
ているらしいです。この条件のWindowがあって、かつ、update_surface_region() の
処理が重い場合に、動作が遅くなる可能性が高いです。Dirty Bitのようなものは、
今のところ見つかっていませんので、何もしなくても常に重くなるのでしょうか。
【詳細】
flush_window_surfaces() なる関数が、定期的に呼び出される。
典型的なタイミングは、PeekMessage() の中からであり、GetMessage()では、
check_for_driver_events() を介して呼び出される。
flush_window_surfaces() の中に次のようなマクロ呼び出しがある :
LIST_FOR_EACH_ENTRY( surface, &window_surfaces, struct window_surface, entry )
surface->funcs->flush( surface );
ここで、
/* iterate through the list using a list entry */
#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
for ((elem) = LIST_ENTRY((list)->next, type, field); \
&(elem)->field != (list); \
(elem) = LIST_ENTRY((elem)->field.next, type, field))
であり、上記は、window_surfaces リストに登録されている全ての
window_surface *surface について、window_surface_funcs *funcs の
関数ポインタ flush の関数を呼び出すことになり、結局、
関数 x11drv_surface_flush() が呼び出されることになる。
関数 x11drv_surface_flush() の中に
if (surface->is_argb || surface->color_key != CLR_INVALID) update_surface_region( surface );
とある。update_surface_region() は、>>418 に書かれている関数。 該当の条件の時、新たには何の描画もしていない静止状態でも、Linuxのシステム・モニターで
CPUパワーが膨大に消費されていることを確認しました。このことは、>>422 を裏付ける物です。
だとすると、Dirty Bit を導入して、update_surface_region()の頻度を下げれば、この低速化
は修正できる可能性が出てきました。LineTo, TextOut, MoveWindow, SetWindowPos,
ShowWindow などを使ったときだけ、DirtyBit を 1にして、1の時だけ update_surface_region()
を呼び出し、呼び出した後には 0 にすれば良いのではないかということです。
条件は:
1. WINEを使用して Windowsアプリを走らせていること。
2. アプリ内で CreateWindowEx() のdwExStyle に WS_EX_LAYERED を指定して Windowを作成
済みであること。
3. さらに、SetLayeredWindowAttribute() に LWA_COLORKEY を指定して「完全透明色」を
指定していること。
4. その Window の背景を「完全透明色」で消去していること。
5. その Window 内部に通常色で、LineTo() や TextOut() によって図形や文字を
描いた後であること。
です。
MDIを使っている事や、CMDIChildWnd 動かすかどうかは関係ない様です。
CMainFrame をドラッグした時には遅く感じないのは、その動作についてはシステムが CPU
の優先順位を上げているからではないかと思います。 >>418 さんの指摘は凄く役立ちました。有難うございます。
ただし、こっちの調査不足のせいが大きいのでしょうが、以下の部分は、今回の
結果とは違っていたようです:
>415の2.,3.の条件だと遅くなるとすると、ピクセル値を比較する処理は1.と同じなので、
>矩形が大量になったときに、X側で描画性能が低下するのではないかと思うぞ。
「X側の描画性能の低下」が原因ではなく、「ピクセル値を比較する処理」自体が、
実は「静止状態」でも、常時、大幅に増加していた、ということです。
何の変化がないときにでも、百万ピクセルを比較し、ランレングスを導き出す処理を、
原則的には秒間20回もやっています。
また、図形が複雑だと、システムコールを呼び出す回数がランレングスの変化の回数倍
されます。例えば、直線をN本引いた場合、システムコールの回数が原則 3N (倍)になります。
縦方向が500ドットのWindowで、1本の直線を引いた場合、一回の処理で、最低でも
6,000回のシステムコールが呼び出されます。これが秒間20回も行われますので、
最低で、秒間12万回のシステムコールとなります。1回のシステムコールは、5(μs)
くらいはどうしてもかかるので、これだけで、0.6(秒)もかかってしまいます。
つまり、1秒間に0.6秒も無駄なシステムコールに時間を取られていると見積もれます。
直線を2本にすると、これだけでCPUがフルパワー状態になります。 【厳密化】
1. 多分、6,000回ではなく、4,500回程度でした。
2. 比較処理自体は、図形の複雑さとは無関係にほぼ一定の重さです。
3. 図形が複雑な場合、システムコールの回数が増えます。
4. 横方向の1つのランレングスで、3つのシステムコールが呼ばれます。
5. 図形が何も描かれていない場合、1つのy座標に対して、1つのランレングスです。
6. N 本の直線の場合、大体で言えば、3N 個のランレングスになります。
7. だから、1つのy座標に対し、9N 個のシステムコールが呼ばれることになります。
8. 縦 500 ドットの場合、500*9N = 4500 N 回のシステムコールとなります。
9. よって、中に描かれている直線の本数が増えると、大体 O(N) で処理時間が
増えます。
10. 文字を描いた場合、大体、文字の複雑さに比例して処理時間が増えます。 >>425
【訂正】
「6.」のランレングスの個数は、3N個ではなく、2N+1 個でした。
お騒がせしました。 >>425
update_surface_regionの方が効率悪そうなので、X側の描画性能が原因と推測した部分は撤回する。
Shape Extensionの仕様を見ると、
矩形領域ではなくマスク用のPixmapを指定する方法も採れるから、
BitBltで効率よくマスクを作ればそっちの方が早くなるかもと思ってみたり。
あと、MDIウィンドウがXのWindowではないことは、xwininfoコマンドの結果でも確認できる。 ■ このスレッドは過去ログ倉庫に格納されています