--- nono/vm/renderer.cpp 2026/04/29 17:04:36 1.1.1.3 +++ nono/vm/renderer.cpp 2026/04/29 17:04:50 1.1.1.4 @@ -4,11 +4,10 @@ // Licensed under nono-license.txt // -#include "object.h" +#include "renderer.h" #include "bitmap.h" #include "bt454.h" #include "mythread.h" -#include "renderer.h" #include "tvram.h" std::unique_ptr gRenderer; @@ -20,6 +19,9 @@ Renderer::Renderer() { logname = "renderer"; devname = "Render"; + + // 初回は必ず描画する? (電源オン直後かな?) + invalidate = true; } // デストラクタ @@ -90,6 +92,16 @@ Renderer::Render() cv.notify_one(); } +// 全画面無効化の指示 (パレット変更で呼ばれる)。 +// ここでは無効化だけ受け付けておいて、実際の処理はレンダリングの際に行う。 +void +Renderer::Invalidate() +{ + std::unique_lock lock(mtx); + request |= REQ_INVALIDATE; + cv.notify_one(); +} + // レンダリングスレッドのエントリポイント void * renderer_run(void *dummy) @@ -118,8 +130,8 @@ Renderer::ThreadRun() if ((req & REQ_TERMINATE)) { // 終了するので、他のフラグは無視 break; - - } else if ((req & REQ_REND_POWEROFF)) { + } + if ((req & REQ_REND_POWEROFF)) { // 電源オフ時の描画 (通常描画フラグは無視) // 電源オフされると画面を灰色にする。 @@ -127,8 +139,16 @@ Renderer::ThreadRun() memset(imagebuf, 0x70, width * height * BPP); // ウィンドウに通知 refresh_callback(); - - } else if ((req & REQ_REND_NORMAL)) { + continue; + } + if ((req & REQ_INVALIDATE)) { + // 全画面無効化の指示。ここではフラグを立てるだけ。 + // パレットは普段はまず変更されないが、変更する時には連続して + // 全パレットが変更されがちなので、ここでフラグを蓄積する。 + // このフラグは同じスレッドの RenderMain() 内で回収する。 + invalidate = true; + } + if ((req & REQ_REND_NORMAL)) { // 通常描画 // レンダラを駆動して @@ -194,11 +214,23 @@ LunaRenderer::~LunaRenderer() { } +bool +LunaRenderer::Init() +{ + if (inherited::Init() == false) { + return false; + } + + // ホストパレット配列を取得。 + pal = gBT454->GetHostPalette(); + return true; +} + + // 画面合成 bool LunaRenderer::RenderMain() { - const uint8 *pal; const uint32 *plane0; std::atomic *dirty; int hscroll; @@ -209,9 +241,6 @@ LunaRenderer::RenderMain() assert(imagebuf); dst0 = imagebuf; - // パレット取得 - pal = gBT454->GetHostPalette(); - // ビットマップ gBitmap->GetRFCNT(&hscroll, &vscroll); const uint8 *mem = gBitmap->GetBuf(); @@ -224,6 +253,15 @@ LunaRenderer::RenderMain() // レンダリング終了時に dirty が 2 なら 0 に戻す。 // これによりレンダリング中に VRAM への書き込みがあれば次回描画される。 + // 全域を無効化して画面全体を描画し直す。 + // XXX この処理中に VRAM 書き込み等があっても整合するんだっけこれ + if (invalidate) { + for (int y = 0; y < height; y++) { + dirty[y] = 1; + } + invalidate = false; + } + // sy はメモリ上の Y 座標 // dy はレンダラ画面の Y 座標 (RFCNT のラスタカウンタを考慮)