--- nono/vm/renderer.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/renderer.h 2026/04/29 17:05:10 1.1.1.7 @@ -1,76 +1,162 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + // // レンダラ // #pragma once -#include "device.h" +// ブロックのヒット効率(?)を測定 +#define PERF_HIT + +#include "thread.h" +#include "bitmap.h" +#include "monitor.h" +#include "spscqueue.h" +#include "stopwatch.h" #include #include -class Renderer : public Device +#if defined(PERF_HIT) +#include "fixedqueue.h" +#endif + +// 更新情報交換用構造体 +struct ModifyInfo { - typedef Device inherited; - public: - // wxWidgets のビットマップは R8_G8_B8 の3バイト。 - static const int BPP = 3; + std::array bits {}; + uint32 n_dirty {}; +#if defined(PERF_HIT) + // 65536 = (2048px / 32bit) * 1024px + std::array dirty_word {}; +#endif + + // パレットを変更した場合とスクロールした場合のように + // composite に変更によらず bitmap を更新する場合は true。 + bool invalidate2 {}; + + void Fill(uint16 v) { + std::fill(bits.begin(), bits.end(), v); + if (v) { + n_dirty = bits.size(); + } else { + n_dirty = 0; + } + } + bool IsClean() const { return n_dirty == 0; } + bool IsDirty() const { return n_dirty != 0; } +}; + +class Renderer : public ThreadDevice +{ + using inherited = ThreadDevice; + public: static const uint REQ_TERMINATE = 0x01; // スレッド終了指示 static const uint REQ_REND_POWEROFF = 0x02; // 電源オフ時の描画指示 static const uint REQ_REND_NORMAL = 0x04; // 通常の描画指示 + static const int BLKX = 128; // 1ブロックの幅 [pixel] + static const int BLKY = 16; // 1ブロックの高さ [pixel] + public: Renderer(); - virtual ~Renderer(); + virtual ~Renderer() override; - virtual bool Init(); - virtual bool PowerOff(); + void ResetHard(bool poweron) override; + void PowerOff() override; - // バッファとコールバック関数を指定 - // XXX 名前... - void SetBuf(uint8 *, void (*)(void)); + // 出力ビットマップを取得 + const BitmapRGB& GetBitmap() { return bitmap; } - // 画面合成処理 (CRTC とかから呼ばれる) + // 合成処理イネーブル + void Enable(); + + // 画面合成処理 (CRTC/CRTC2 から呼ばれる) void Render(); + // 全画面更新の指示 (パレット変更とスクロール座標変更で呼ばれる) + void Invalidate2(); + // 仮想画面幅(ピクセル)を取得 int GetWidth() const { return width; } // 仮想画面高さ(ピクセル)を取得 int GetHeight() const { return height; } - // レンダリングスレッド (エントリポイントから呼ばれる) - void ThreadRun(); + // 描画更新(通知)間隔を設定 (GUI から呼ばれる) + void SetRefreshInterval(uint64 t); protected: + // レンダリングスレッド + void ThreadRun() override; + // 画面合成。更新があれば true を返す。(派生クラス側で用意) virtual bool RenderMain() = 0; + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + // ウィンドウとして表示される画面はオプションや設定などで縮尺を変える // ことが出来るが (こっちを実画面とする)、ここで扱う仮想画面とはそれに // 関わらず常にその機種の最大描画面積を指す。 // LUNA でいう 1280 x 1024 のこと。 // 仮想画面幅(ピクセル) - int width = 0; + int width {}; // 仮想画面高さ(ピクセル) - int height = 0; + int height {}; - // バッファ (実体は wx 側で用意) - uint8 *imagebuf = NULL; + // レンダリング結果のビットマップ + BitmapRGB bitmap {}; - // リフレッシュを指示するためのコールバック (wx 側で用意) - // ここから直接 wxWindow::Refresh() を呼べないため。 - void (*refresh_callback)(void) = NULL; + // ステージ2 の全画面更新指示フラグ + bool invalidate2 {}; // リクエストフラグ - uint32 request = 0; + uint32 request {}; std::mutex mtx {}; std::condition_variable cv {}; + + // 合成処理有効フラグ + bool enable {}; + + // 更新情報を VM -> Renderer スレッドに渡すための 1 要素キュー + SPSCQueue modq {}; + + // レンダラスレッドで受け取った更新情報 (モニタ表示のため) + ModifyInfo modify {}; + + // 画面更新を UI に通知する間隔 + uint64 refresh_interval {}; + // 次回更新を通知する実時刻 + uint64 next_refresh_rtime {}; + + // 出力画面に更新がある (UI に通知する必要がある) 場合は true + bool out_dirty {}; + + // 統計情報 + uint64 render_exec {}; // RenderMain() の実行回数 + Stopwatch render_time {}; // RenderMain() の総実行時間 + uint32 last_mod_blocks {}; // 直近の更新ブロック数 + uint64 total_mod_blocks {}; // 総更新ブロック数 + uint64 total_invalidate2 {}; // ステージ2の全画面更新回数 + +#if defined(PERF_HIT) + FixedQueue hitrate_ma {}; + uint64 hitrate_total_word {}; + uint64 hitrate_total_block {}; +#endif + + Monitor monitor { this }; + + private: + // スレッドの終了を指示 + void Terminate() override; }; // @@ -78,12 +164,12 @@ class Renderer : public Device // class X68030Renderer : public Renderer { - typedef Renderer inherited; + using inherited = Renderer; public: X68030Renderer(); - virtual ~X68030Renderer(); + virtual ~X68030Renderer() override; - virtual bool RenderMain(); + bool RenderMain() override; }; // @@ -91,12 +177,15 @@ class X68030Renderer : public Renderer // class LunaRenderer : public Renderer { - typedef Renderer inherited; + using inherited = Renderer; public: LunaRenderer(); - virtual ~LunaRenderer(); + virtual ~LunaRenderer() override; + + // 合成ビットマップを取得 + const BitmapI8& GetComposite() const; - virtual bool RenderMain(); + bool RenderMain() override; }; extern Renderer *gRenderer;