2024/04/02(火) [n年前の日記]
#1 [prog] 自作スクリーンセーバが起動しにくい問題について試行錯誤中
_昨日githubにアップロード
した、C++ (MinGW g++ 6.3.0) と OpenGL で自作したWindows用スクリーンセーバが、サブPC上で起動しにくい問題について、解決策がないか試しているところ。
状況は以下。
つまり、スクリーンセーバとして作ると、サブPC上で利用しようとした時だけ、動いたり動かなかったりする状態になってしまう。
状況は以下。
- メインPC上ではすんなり動く。
- サブPC上では動いたり動かなかったりする。
- GLFWで新規にウインドウを作成して、そのウインドウに描画する版なら、サブPC上でもすんなり動く。
- Windowsのイベントビューアにクラッシュ情報は記録されていない。
つまり、スクリーンセーバとして作ると、サブPC上で利用しようとした時だけ、動いたり動かなかったりする状態になってしまう。
◎ 初期化処理は最低限の処理だけにしておくと良さそう :
スクリーンセーバを作る際の前提として、以下があるわけだけど…。
ふと、WM_CREATE が飛んできた際、そこで時間がかかる初期化処理をしてしまうとよろしくないのではないか…? と思えてきた。昨日の段階では、WM_CREATE が来た時に画像の展開処理もしていて、そこで数秒待たされる状態になっていた。
試しに、WM_CREATE が来た時は最低限の初期化処理だけをして、画像の展開は各フレーム処理内で行うように変更してみた。更に、展開すべき画像5枚分を一気に展開せず、1フレームにつき画像を1枚ずつ展開して、5フレームかけて全画像を展開するようにした。
このように変更したところ、サブPC上でも、スクリーンセーバが起動してくれる確率がグンと上がった。
- C/C++ (MinGW gcc/g++ 6.3.0) でスクリーンセーバを作る際、scrnsaveライブラリを使うと作りやすくなる。scrnsave.h を include して、libscrnsave.a をリンクする。
- scrnsaveライブラリを使えば、たった3つの関数 ―― ScreenSaverProc()、ScreenSaverConfigureDialog(), RegisterDialogClasses() を自分で書くだけでスクリーンセーバが作れる。
- ScreenSaverProc() 内で、WM_CREATEメッセージが送られてきたら初期化処理を行い、SetTimer() で一定時間毎に処理が呼ばれるように ―― 指定時間毎に WM_TIMER が送られてくるように指定する。
- ScreenSaverProc() 内で、WM_TIMERメッセージが送られてきたら、毎フレームの処理を行う。
ふと、WM_CREATE が飛んできた際、そこで時間がかかる初期化処理をしてしまうとよろしくないのではないか…? と思えてきた。昨日の段階では、WM_CREATE が来た時に画像の展開処理もしていて、そこで数秒待たされる状態になっていた。
試しに、WM_CREATE が来た時は最低限の初期化処理だけをして、画像の展開は各フレーム処理内で行うように変更してみた。更に、展開すべき画像5枚分を一気に展開せず、1フレームにつき画像を1枚ずつ展開して、5フレームかけて全画像を展開するようにした。
このように変更したところ、サブPC上でも、スクリーンセーバが起動してくれる確率がグンと上がった。
- リモートデスクトップソフト Brynhildr をサーバモードで常駐させていても、起動する確率は高い。
- 1920x1200の画面でも、全てが問題無く描画できるようになった。
◎ 残っている問題 :
ただ、これでもまだ問題が残ってる。
メインPC上ではこんな問題は起きてない。サブPC上でだけ起きてるのだよな…。AMD製GPU(Radeon R3)のせい…?
- 最初の呼び出し時は、一瞬画面がチラついて、すぐにスクリーンセーバが終了してしまう。
- そのまま放置して2度目の呼び出しが来ると、今度はちゃんとスクリーンセーバが起動してくれる。
メインPC上ではこんな問題は起きてない。サブPC上でだけ起きてるのだよな…。AMD製GPU(Radeon R3)のせい…?
◎ 2024/04/03追記 :
原因が分かった。デスクトップ解像度が1920x1200になっているとこの不具合が発生する。1920x1080にすれば一発でスクリーンセーバが起動する。そんなオチかよ…。トホホ。
[ ツッコむ ]
以上、1 日分です。