--- nono/vm/renderer.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/renderer.h 2026/04/29 17:05:25 1.1.1.10 @@ -1,76 +1,159 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + // // レンダラ // #pragma once -#include "device.h" +#include "thread.h" +#include "bitmap.h" +#include "monitor.h" +#include "spscqueue.h" +#include "stopwatch.h" #include #include -class Renderer : public Device +class PlaneVRAMDevice; +class Syncer; +class VideoCtlrDevice; + +// 更新情報交換用構造体 +struct ModifyInfo { - typedef Device inherited; - public: - // wxWidgets のビットマップは R8_G8_B8 の3バイト。 - static const int BPP = 3; + std::array bits {}; + uint32 n_dirty {}; + + // パレットを変更した場合とスクロールした場合のように + // composite に変更によらず bitmap を更新する場合は true。 + bool invalidate2 {}; + + void Fill(uint8 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; // 通常の描画指示 public: Renderer(); - virtual ~Renderer(); + ~Renderer() override; - virtual bool Init(); - virtual bool PowerOff(); + bool Init() override; + 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; + // RGBX から RGB への変換。 + void RGBXtoRGB(BitmapRGB& dst, const BitmapRGBX& src); + + 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の全画面更新回数 + + PlaneVRAMDevice *planevram {}; + Syncer *syncer {}; + + Monitor monitor { this }; + + private: + // スレッドの終了を指示 + void Terminate() override; + + static void RGBXtoRGB_gen(BitmapRGB& dst, const BitmapRGBX& src); +#if defined(HAVE_AVX2) + static void RGBXtoRGB_avx2(BitmapRGB& dst, const BitmapRGBX& src); + bool enable_avx2 {}; +#endif }; // @@ -78,12 +161,18 @@ class Renderer : public Device // class X68030Renderer : public Renderer { - typedef Renderer inherited; + using inherited = Renderer; public: X68030Renderer(); - virtual ~X68030Renderer(); + ~X68030Renderer() override; - virtual bool RenderMain(); + bool Init() override; + bool RenderMain() override; + + private: + BitmapRGBX bitmap32 {}; + + VideoCtlrDevice *videoctlr {}; }; // @@ -91,12 +180,31 @@ class X68030Renderer : public Renderer // class LunaRenderer : public Renderer { - typedef Renderer inherited; + using inherited = Renderer; public: LunaRenderer(); - virtual ~LunaRenderer(); + ~LunaRenderer() override; + + bool Init() override; + bool RenderMain() override; + + private: + BitmapRGBX textbmp {}; +}; + +// +// 何もしないレンダラ +// +class NopRenderer : public Renderer +{ + using inherited = Renderer; + public: + NopRenderer(); + ~NopRenderer() override; - virtual bool RenderMain(); + bool RenderMain() override; }; -extern Renderer *gRenderer; +static inline Renderer *GetRenderer() { + return Object::GetObject(OBJ_RENDERER); +}