|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// ビデオレンダラ
//
#pragma once
#include "thread.h"
#include "bitmap.h"
#include "fixedqueue.h"
#include <condition_variable>
#include <mutex>
class ConsoleDevice;
class PlaneVRAMDevice;
class Syncer;
class UIMessage;
class VideoCtlrDevice;
class VideoRenderer : public ThreadDevice
{
using inherited = ThreadDevice;
public:
static const uint REQ_TERMINATE = 0x01; // スレッド終了指示
static const uint REQ_SCREENOFF = 0x02; // 電源オフ時の描画指示
static const uint REQ_RENDER = 0x04; // 通常の描画指示
static const uint REQ_RESIZE = 0x08; // リサイズ指示
static const uint REQ_POST = 0x10; // UI への通知指示
public:
VideoRenderer();
~VideoRenderer() override;
bool Init() override;
void ResetHard(bool poweron) override;
void PowerOff() override;
// 出力ビットマップが有効なら取得。
// (wxImage に渡すため const なし)
BitmapRGB *GetBitmap() {
if (__predict_true(bitmap24_valid)) {
return bitmap24.get();
} else {
return NULL;
}
}
// 画面合成処理の指示 (CRTC/CRTC2 から呼ばれる)
void NotifyRender();
// 表示画面サイズを設定 (GUI から呼ばれる)
void ResizeView(uint width_, uint height_);
// 仮想画面幅(ピクセル)を取得
uint GetWidth() const { return width; }
// 仮想画面高さ(ピクセル)を取得
uint GetHeight() const { return height; }
// 描画更新(通知)間隔を設定 (GUI から呼ばれる)
void SetRefreshInterval(uint64 msec);
protected:
// レンダリングスレッド
void ThreadRun() override;
// 描画する。
int64 DoRender(uint32 req);
// 画面合成。更新があれば true を返す。(派生クラス側で用意)
virtual bool RenderMD() = 0;
void PrintPerf();
DECLARE_MONITOR_SCREEN(MonitorScreen);
// ウィンドウとして表示される画面はオプションや設定などで縮尺を変える
// ことが出来るが (こっちを実画面とする)、ここで扱う仮想画面とはそれに
// 関わらず常にその機種の最大描画面積を指す。
// LUNA でいう 1280 x 1024 のこと。
// 仮想画面幅(ピクセル)
uint width {};
// 仮想画面高さ(ピクセル)
uint height {};
// レンダリング結果のビットマップ
BitmapRGBX bitmap {};
// wxWidgets 用表示ビットマップ
std::unique_ptr<BitmapRGB> bitmap24 /*{}*/;
// 表示ビットマップの大きさ
Rect viewrect {};
// リクエストフラグ
uint32 request {};
std::mutex mtx {};
std::condition_variable cv {};
// リサイズ時の要求サイズ
uint new_viewwidth {};
uint new_viewheight {};
// レンダラ有効フラグ (GUI なら true)
bool enable {};
// 初期化やリサイズ後に一度でも bitmap24 を更新すれば true。
bool bitmap24_valid {};
// 画面更新を UI に通知する間隔
uint64 refresh_interval {};
// 次回更新を通知する実時刻
uint64 next_refresh_rtime {};
// 統計情報
uint64 stat_input_count {}; // 入力通知回数
uint64 last_input_time {}; // 前回の入力通知 VM 時刻
FixedQueue<uint64, 4> ma_input_span {}; // 入力通知間隔
uint64 stat_render_count {}; // RenderMD() の実行回数
uint64 stat_noupdate_count {}; // bitmap24 への更新が不要だった回数
uint64 stat_nobitmap_count {}; // bitmap24 が用意できてなかった回数
uint64 stat_output_count {}; // UI への出力通知回数
uint64 last_output_time {}; // 前回の出力通知 RT 時刻
FixedQueue<uint64, 4> ma_output_span {}; // 出力通知間隔
Syncer *syncer {};
UIMessage *uimessage {};
Monitor *monitor {};
private:
// スレッドの終了を指示
void Terminate() override;
};
//
// X68030 レンダラ
//
class X68030VideoRenderer : public VideoRenderer
{
using inherited = VideoRenderer;
public:
X68030VideoRenderer();
~X68030VideoRenderer() override;
bool Init() override;
bool RenderMD() override;
private:
VideoCtlrDevice *videoctlr {};
};
//
// LUNA レンダラ
//
class LunaVideoRenderer : public VideoRenderer
{
using inherited = VideoRenderer;
public:
LunaVideoRenderer();
~LunaVideoRenderer() override;
bool Init() override;
bool RenderMD() override;
private:
PlaneVRAMDevice *planevram {};
};
//
// コンソールレンダラ
//
class ConsoleRenderer : public VideoRenderer
{
using inherited = VideoRenderer;
public:
// フチ [pixel]
static const uint Padding = 3;
public:
ConsoleRenderer();
~ConsoleRenderer() override;
bool Init() override;
bool RenderMD() override;
private:
ConsoleDevice *console {};
};
inline VideoRenderer *GetVideoRenderer() {
return Object::GetObject<VideoRenderer>(OBJ_VIDEO_RENDERER);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.