--- nono/vm/renderer.cpp 2026/04/29 17:05:28 1.1.1.10 +++ nono/vm/renderer.cpp 2026/04/29 17:05:32 1.1.1.11 @@ -9,6 +9,8 @@ // #include "renderer.h" +#include "console.h" +#include "monitor.h" #include "planevram.h" #include "scheduler.h" #include "syncer.h" @@ -18,8 +20,6 @@ #if 0 #define PERFREND #include "stopwatch.h" -static uint64 check_time; -static uint check_count; static Stopwatch sw_notify; static uint64 notify_time; static uint notify_count; @@ -36,6 +36,9 @@ static const Color ScreenOffColor(0x70, Renderer::Renderer() : inherited(OBJ_RENDERER) { + monitor = gMonitorManager->Regist(ID_MONITOR_RENDERER, this); + monitor->func = ToMonitorCallback(&Renderer::MonitorUpdate); + monitor->SetSize(42, 10); } // デストラクタ @@ -44,15 +47,6 @@ Renderer::~Renderer() TerminateThread(); } -// モニタを初期化する (継承先コンストラクタから必要なら呼ばれる) -void -Renderer::InitMonitor() -{ - monitor.func = ToMonitorCallback(&Renderer::MonitorUpdate); - monitor.SetSize(42, 16); - monitor.Regist(ID_MONITOR_RENDERER); -} - // 初期化 bool Renderer::Init() @@ -86,16 +80,12 @@ Renderer::ResetHard(bool poweron) stat_input_count = 0; last_input_time = now; ma_input_span.Clear(); - stat_enqueue_count = 0; - stat_enqueue_full = 0; stat_render_count = 0; stat_noupdate_count = 0; stat_nobitmap_count = 0; stat_output_count = 0; last_output_time = now; ma_output_span.Clear(); - last_mod_lines = 0; - total_invalidate2 = 0; } // 電源オフ @@ -103,6 +93,9 @@ void Renderer::PowerOff() { if (enable) { +#if defined(PERFREND) + sw_notify.Restart(); +#endif // レンダリングスレッドに指示 std::unique_lock lock(mtx); request |= REQ_SCREENOFF; @@ -110,7 +103,7 @@ Renderer::PowerOff() } } -// 画面合成処理 (VM スレッドで CRTC/CRTC2 から呼ばれる)。 +// 画面合成処理 (VM スレッドで呼ばれる)。 // 今は一画面単位で合成を行なっている。ラスター云々は未対応。 void Renderer::NotifyRender() @@ -126,53 +119,18 @@ Renderer::NotifyRender() ma_input_span.EnqueueForce(now - last_input_time); last_input_time = now; - // 更新されていればレンダラに引き渡す #if defined(PERFREND) - Stopwatch sw; - sw.Start(); + sw_notify.Restart(); #endif - ModifyInfo mod; - bool dirty = GetModifyMD(&mod); - if (__predict_false(invalidate2 == true)) { - mod.invalidate2 = true; - } - if (dirty || mod.invalidate2) { - if (modq.Enqueue(mod)) { -#if defined(PERFREND) - // 更新チェックしてキューに入れるまでにかかる VM スレッド側時間 - sw.Stop(); - check_time += sw.Elapsed(); - check_count++; -#endif - // 更新情報を引き取ったのでクリアする - ClearDirtyMD(); - invalidate2 = false; - - stat_enqueue_count++; - -#if defined(PERFREND) - // スレッドをまたぐのにかかる時間 - sw_notify.Restart(); -#endif - // 描画指示。 - std::unique_lock lock(mtx); - request |= REQ_RENDER; - cv.notify_one(); - } else { - stat_enqueue_full++; - } + // レンダラスレッドに描画指示を出すだけ。 + { + std::unique_lock lock(mtx); + request |= REQ_RENDER; + cv.notify_one(); } } -// 全画面更新の指示 (パレット変更やスクロールなど VRAM の変更を伴わないもの)。 -// ここでは無効化だけ受け付けておいて、実際の処理はレンダリングの際に行う。 -void -Renderer::Invalidate2() -{ - invalidate2 = true; -} - // レンダリングスレッド void Renderer::ThreadRun() @@ -250,26 +208,16 @@ Renderer::DoRender(uint32 req) sw_notify.Stop(); notify_time += sw_notify.Elapsed(); notify_count++; -#endif - if (modq.Dequeue(&modify)) { - // 更新ライン数を数える (統計用) - last_mod_lines = modify.GetDirtyCount(); - if (__predict_false(modify.invalidate2)) { - total_invalidate2++; - } - - // レンダラを駆動する。 -#if defined(PERFREND) - sw.Restart(); + sw.Restart(); #endif - updated = RenderMD(); + // レンダラを駆動する。 + updated = RenderMD(); #if defined(PERFREND) - sw.Stop(); - render_time += sw.Elapsed(); + sw.Stop(); + render_time += sw.Elapsed(); #endif - stat_render_count++; - } + stat_render_count++; } if ((req & REQ_SCREENOFF)) { // 電源オン→オフ時の描画 @@ -336,9 +284,7 @@ Renderer::DoRender(uint32 req) #if defined(PERFREND) if (++convert_count % 100 == 0) { - printf("Check %4.2f, Notify %u, Render %u, Stretch %u, Convert %u" - " [usec]\n", - (double)check_time / check_count / 1000, + printf("Notify %u, Render %u, Stretch %u, Convert %u [usec]\n", (uint)(notify_time / notify_count / 1000U), (uint)(render_time / stat_render_count / 1000U), (uint)(stretch_time / convert_count / 1000U), @@ -420,12 +366,6 @@ Renderer::MonitorUpdate(Monitor *, TextS y++; y++; - screen.Puts(0, y, "Enqueue Count"); - screen.Print(x, y++, "%26s", format_number(stat_enqueue_count).c_str()); - screen.Puts(0, y, "Enqueue Full"); - screen.Print(x, y++, "%26s", format_number(stat_enqueue_full).c_str()); - - y++; screen.Puts(0, y, "RenderMD Count"); screen.Print(x, y++, "%26s", format_number(stat_render_count).c_str()); screen.Puts(0, y, "NoUpdate Count"); @@ -448,12 +388,6 @@ Renderer::MonitorUpdate(Monitor *, TextS screen.Print(x + 18, y, "%5.1f Hz", ma == 0 ? 0.0 : (double)1000'000'000 / ma); y++; - - y++; - screen.Puts(0, y, "Last Mod Lines"); - screen.Print(x, y++, "%26u", last_mod_lines); - screen.Puts(0, y, "Invalidate2"); - screen.Print(x, y++, "%26s", format_number(total_invalidate2).c_str()); } @@ -464,8 +398,6 @@ Renderer::MonitorUpdate(Monitor *, TextS // コンストラクタ X68030Renderer::X68030Renderer() { - InitMonitor(); - // XXX とりあえず width = 768; height = 512; @@ -486,34 +418,16 @@ X68030Renderer::Init() return false; } - planevram = GetPlaneVRAMDevice(); videoctlr = GetVideoCtlrDevice(); return true; } -// 更新チェック -bool -X68030Renderer::GetModifyMD(ModifyInfo *mod) const -{ - // 今のところテキスト VRAM しかない - // TODO: videoctlr に移動 - return planevram->GetModify(mod); -} - -// 更新情報クリア -void -X68030Renderer::ClearDirtyMD() -{ - // 今のところテキスト VRAM しかない - planevram->ClearDirty(); -} - // 画面合成 bool X68030Renderer::RenderMD() { - bool updated = videoctlr->Render(bitmap, modify); + bool updated = videoctlr->Render(bitmap); return updated; } @@ -525,8 +439,6 @@ X68030Renderer::RenderMD() // コンストラクタ LunaRenderer::LunaRenderer() { - InitMonitor(); - width = 1280; height = 1024; @@ -551,62 +463,51 @@ LunaRenderer::Init() return true; } -// 更新チェック -bool -LunaRenderer::GetModifyMD(ModifyInfo *mod) const -{ - return planevram->GetModify(mod); -} - -// 更新情報クリア -void -LunaRenderer::ClearDirtyMD() -{ - planevram->ClearDirty(); -} - // 画面合成 bool LunaRenderer::RenderMD() { - bool updated = planevram->Render(bitmap, modify); + bool updated = planevram->Render(bitmap); return updated; } // -// 何もしないレンダラ +// コンソールレンダラ // // コンストラクタ -NopRenderer::NopRenderer() +ConsoleRenderer::ConsoleRenderer() { - // XXX サポートしてない - width = 640; - height = 480; + // 視認性のためフチを追加。 + width = 640 + Padding * 2; + height = 480 + Padding * 2; + + bitmap.Create(width, height); } // デストラクタ -NopRenderer::~NopRenderer() +ConsoleRenderer::~ConsoleRenderer() { } -// 更新チェック +// 初期化 bool -NopRenderer::GetModifyMD(ModifyInfo *) const +ConsoleRenderer::Init() { - return false; -} + if (inherited::Init() == false) { + return false; + } -// 更新情報クリア -void -NopRenderer::ClearDirtyMD() -{ + console = GetConsoleDevice(); + + return true; } // 画面合成 bool -NopRenderer::RenderMD() +ConsoleRenderer::RenderMD() { - return false; + bool updated = console->Render(bitmap); + return updated; }