|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
1.1 root 7: //
8: // レンダラ
9: //
10:
11: #pragma once
12:
1.1.1.7 root 13: // ブロックのヒット効率(?)を測定
14: #define PERF_HIT
15:
16: #include "thread.h"
17: #include "bitmap.h"
18: #include "monitor.h"
19: #include "spscqueue.h"
20: #include "stopwatch.h"
1.1 root 21: #include <condition_variable>
22: #include <mutex>
23:
1.1.1.7 root 24: #if defined(PERF_HIT)
25: #include "fixedqueue.h"
26: #endif
27:
28: // 更新情報交換用構造体
29: struct ModifyInfo
1.1 root 30: {
1.1.1.7 root 31: std::array<uint16, 64> bits {};
32: uint32 n_dirty {};
33: #if defined(PERF_HIT)
34: // 65536 = (2048px / 32bit) * 1024px
35: std::array<bool, 65536> dirty_word {};
36: #endif
37:
38: // パレットを変更した場合とスクロールした場合のように
39: // composite に変更によらず bitmap を更新する場合は true。
40: bool invalidate2 {};
41:
42: void Fill(uint16 v) {
43: std::fill(bits.begin(), bits.end(), v);
44: if (v) {
45: n_dirty = bits.size();
46: } else {
47: n_dirty = 0;
48: }
49: }
50:
51: bool IsClean() const { return n_dirty == 0; }
52: bool IsDirty() const { return n_dirty != 0; }
53: };
1.1 root 54:
1.1.1.7 root 55: class Renderer : public ThreadDevice
56: {
57: using inherited = ThreadDevice;
58: public:
1.1 root 59: static const uint REQ_TERMINATE = 0x01; // スレッド終了指示
60: static const uint REQ_REND_POWEROFF = 0x02; // 電源オフ時の描画指示
61: static const uint REQ_REND_NORMAL = 0x04; // 通常の描画指示
1.1.1.7 root 62:
63: static const int BLKX = 128; // 1ブロックの幅 [pixel]
64: static const int BLKY = 16; // 1ブロックの高さ [pixel]
1.1 root 65:
66: public:
67: Renderer();
1.1.1.5 root 68: virtual ~Renderer() override;
1.1 root 69:
1.1.1.7 root 70: void ResetHard(bool poweron) override;
71: void PowerOff() override;
1.1 root 72:
1.1.1.7 root 73: // 出力ビットマップを取得
74: const BitmapRGB& GetBitmap() { return bitmap; }
1.1 root 75:
1.1.1.7 root 76: // 合成処理イネーブル
77: void Enable();
78:
79: // 画面合成処理 (CRTC/CRTC2 から呼ばれる)
1.1 root 80: void Render();
81:
1.1.1.7 root 82: // 全画面更新の指示 (パレット変更とスクロール座標変更で呼ばれる)
83: void Invalidate2();
1.1.1.6 root 84:
1.1 root 85: // 仮想画面幅(ピクセル)を取得
86: int GetWidth() const { return width; }
87:
88: // 仮想画面高さ(ピクセル)を取得
89: int GetHeight() const { return height; }
90:
1.1.1.7 root 91: // 描画更新(通知)間隔を設定 (GUI から呼ばれる)
92: void SetRefreshInterval(uint64 t);
1.1 root 93:
94: protected:
1.1.1.7 root 95: // レンダリングスレッド
96: void ThreadRun() override;
97:
1.1 root 98: // 画面合成。更新があれば true を返す。(派生クラス側で用意)
99: virtual bool RenderMain() = 0;
100:
1.1.1.7 root 101: DECLARE_MONITOR_CALLBACK(MonitorUpdate);
102:
1.1 root 103: // ウィンドウとして表示される画面はオプションや設定などで縮尺を変える
104: // ことが出来るが (こっちを実画面とする)、ここで扱う仮想画面とはそれに
105: // 関わらず常にその機種の最大描画面積を指す。
106: // LUNA でいう 1280 x 1024 のこと。
107:
108: // 仮想画面幅(ピクセル)
1.1.1.4 root 109: int width {};
1.1 root 110:
111: // 仮想画面高さ(ピクセル)
1.1.1.4 root 112: int height {};
1.1 root 113:
1.1.1.7 root 114: // レンダリング結果のビットマップ
115: BitmapRGB bitmap {};
1.1 root 116:
1.1.1.7 root 117: // ステージ2 の全画面更新指示フラグ
118: bool invalidate2 {};
1.1.1.6 root 119:
1.1 root 120: // リクエストフラグ
1.1.1.4 root 121: uint32 request {};
1.1 root 122: std::mutex mtx {};
123: std::condition_variable cv {};
1.1.1.2 root 124:
1.1.1.7 root 125: // 合成処理有効フラグ
126: bool enable {};
127:
128: // 更新情報を VM -> Renderer スレッドに渡すための 1 要素キュー
129: SPSCQueue<ModifyInfo, 1> modq {};
130:
131: // レンダラスレッドで受け取った更新情報 (モニタ表示のため)
132: ModifyInfo modify {};
1.1.1.2 root 133:
1.1.1.7 root 134: // 画面更新を UI に通知する間隔
135: uint64 refresh_interval {};
136: // 次回更新を通知する実時刻
137: uint64 next_refresh_rtime {};
138:
139: // 出力画面に更新がある (UI に通知する必要がある) 場合は true
140: bool out_dirty {};
141:
142: // 統計情報
143: uint64 render_exec {}; // RenderMain() の実行回数
144: Stopwatch render_time {}; // RenderMain() の総実行時間
145: uint32 last_mod_blocks {}; // 直近の更新ブロック数
146: uint64 total_mod_blocks {}; // 総更新ブロック数
147: uint64 total_invalidate2 {}; // ステージ2の全画面更新回数
148:
149: #if defined(PERF_HIT)
150: FixedQueue<double, 10> hitrate_ma {};
151: uint64 hitrate_total_word {};
152: uint64 hitrate_total_block {};
153: #endif
154:
155: Monitor monitor { this };
156:
157: private:
1.1.1.2 root 158: // スレッドの終了を指示
1.1.1.7 root 159: void Terminate() override;
1.1 root 160: };
161:
162: //
163: // X68030 レンダラ
164: //
165: class X68030Renderer : public Renderer
166: {
1.1.1.3 root 167: using inherited = Renderer;
1.1 root 168: public:
169: X68030Renderer();
1.1.1.5 root 170: virtual ~X68030Renderer() override;
1.1 root 171:
1.1.1.3 root 172: bool RenderMain() override;
1.1 root 173: };
174:
175: //
176: // LUNA レンダラ
177: //
178: class LunaRenderer : public Renderer
179: {
1.1.1.3 root 180: using inherited = Renderer;
1.1 root 181: public:
182: LunaRenderer();
1.1.1.5 root 183: virtual ~LunaRenderer() override;
1.1 root 184:
1.1.1.3 root 185: bool RenderMain() override;
1.1 root 186: };
187:
1.1.1.7 root 188: extern Renderer *gRenderer;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.