Annotation of nono/vm/renderer.cpp, revision 1.1.1.8

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.6   root        7: //
                      8: // レンダラ
                      9: //
                     10: 
1.1.1.4   root       11: #include "renderer.h"
1.1.1.5   root       12: #include "lunafb.h"
1.1.1.8 ! root       13: #include "syncer.h"
1.1.1.6   root       14: #include "uimessage.h"
1.1       root       15: 
                     16: // コンストラクタ
                     17: Renderer::Renderer()
1.1.1.8 ! root       18:        : inherited(OBJ_RENDERER)
1.1       root       19: {
1.1.1.6   root       20:        monitor.func = ToMonitorCallback(&X68030Renderer::MonitorUpdate);
                     21:        monitor.SetSize(68, 33);
                     22:        monitor.Regist(ID_MONITOR_RENDERER);
1.1       root       23: }
                     24: 
                     25: // デストラクタ
                     26: Renderer::~Renderer()
                     27: {
1.1.1.6   root       28:        TerminateThread();
1.1.1.8 ! root       29: }
        !            30: 
        !            31: // 初期化
        !            32: bool
        !            33: Renderer::Init()
        !            34: {
        !            35:        if (inherited::Init() == false) {
        !            36:                return false;
        !            37:        }
        !            38: 
        !            39:        // NEWS にはまだ VRAM 等のデバイスがない
        !            40:        if (gMainApp.IsNEWS() == false) {
        !            41:                planevram = GetPlaneVRAMDevice();
        !            42:        }
        !            43:        syncer = GetSyncer();
        !            44: 
        !            45:        return true;
1.1       root       46: }
                     47: 
1.1.1.6   root       48: // リセット
                     49: void
                     50: Renderer::ResetHard(bool poweron)
1.1       root       51: {
1.1.1.8 ! root       52:        next_refresh_rtime = syncer->GetRealTime();
1.1       root       53: 
1.1.1.6   root       54:        // 統計情報をクリア
                     55:        render_time.Reset();
                     56:        render_exec = 0;
                     57:        last_mod_blocks = 0;
                     58:        total_mod_blocks = 0;
                     59:        total_invalidate2 = 0;
1.1       root       60: }
                     61: 
1.1.1.6   root       62: // 電源オフ
                     63: void
1.1       root       64: Renderer::PowerOff()
                     65: {
1.1.1.6   root       66:        if (enable) {
1.1       root       67:                // レンダリングスレッドに指示
                     68:                std::unique_lock<std::mutex> lock(mtx);
                     69:                request |= REQ_REND_POWEROFF;
                     70:                cv.notify_one();
                     71:        }
                     72: }
                     73: 
1.1.1.6   root       74: // 合成処理イネーブル
                     75: // 一度だけ呼び出すことができる
1.1       root       76: void
1.1.1.6   root       77: Renderer::Enable()
1.1       root       78: {
1.1.1.6   root       79:        assert(enable == false);
1.1       root       80: 
1.1.1.6   root       81:        enable = true;
                     82:        bitmap.Create(width, height);
                     83:        // 初期値灰色にしておく
                     84:        bitmap.Fill(Color(0x70, 0x70, 0x70));
1.1       root       85: }
                     86: 
1.1.1.6   root       87: // 画面合成処理 (VM スレッドで CRTC/CRTC2 から呼ばれる)。
1.1       root       88: // 今は一画面単位で合成を行なっている。ラスター云々は未対応。
                     89: void
                     90: Renderer::Render()
                     91: {
                     92:        // CLI 版なら何もしない。
1.1.1.6   root       93:        if (enable == false) {
1.1       root       94:                return;
                     95:        }
                     96: 
1.1.1.6   root       97:        // 更新されていればレンダラに引き渡す
1.1.1.8 ! root       98:        ModifyInfo mod = planevram->GetModify();
1.1.1.6   root       99:        if (__predict_false(invalidate2 == true)) {
                    100:                mod.invalidate2 = true;
                    101:        }
                    102: 
                    103:        if (mod.IsDirty() || mod.invalidate2) {
                    104:                if (modq.Enqueue(mod)) {
                    105:                        // 更新情報を引き取ったのでクリアする
1.1.1.8 ! root      106:                        planevram->ClearDirty();
1.1.1.6   root      107:                        invalidate2 = false;
                    108:                } else {
                    109:                        // VM スレッドが速すぎるため次回に持ち越し
                    110:                }
                    111:        }
                    112: 
1.1       root      113:        // スケジューラ都合による間引きとかがあればここらへんで評価?
                    114:        // XXX どっちのスレッドでやるか
                    115: 
                    116:        // レンダリングスレッドに指示
                    117:        std::unique_lock<std::mutex> lock(mtx);
                    118:        request |= REQ_REND_NORMAL;
                    119:        cv.notify_one();
                    120: }
                    121: 
1.1.1.6   root      122: // 全画面更新の指示 (パレット変更やスクロールなど VRAM の変更を伴わないもの)。
1.1.1.4   root      123: // ここでは無効化だけ受け付けておいて、実際の処理はレンダリングの際に行う。
                    124: void
1.1.1.6   root      125: Renderer::Invalidate2()
1.1.1.4   root      126: {
1.1.1.6   root      127:        invalidate2 = true;
1.1       root      128: }
                    129: 
                    130: // レンダリングスレッド
                    131: void
                    132: Renderer::ThreadRun()
                    133: {
                    134:        for (;;) {
                    135:                uint32 req;
                    136: 
                    137:                // 何か起きるまで待つ
                    138:                {
                    139:                        std::unique_lock<std::mutex> lock(mtx);
                    140:                        cv.wait(lock, [&] { return (request != 0); });
                    141:                        req = request;
                    142:                        request = 0;
                    143:                }
                    144: 
                    145:                if ((req & REQ_TERMINATE)) {
                    146:                        // 終了するので、他のフラグは無視
                    147:                        break;
1.1.1.4   root      148:                }
                    149:                if ((req & REQ_REND_POWEROFF)) {
1.1       root      150:                        // 電源オフ時の描画 (通常描画フラグは無視)
                    151: 
                    152:                        // 電源オフされると画面を灰色にする。
                    153:                        // 黒でもいいけど、電源オンで黒いままなのと区別したい。
1.1.1.6   root      154:                        bitmap.Fill(Color(0x70, 0x70, 0x70));
                    155:                        // UI に通知
                    156:                        UIMessage::Post(UIMessage::RENDER);
1.1.1.4   root      157:                        continue;
                    158:                }
                    159:                if ((req & REQ_REND_NORMAL)) {
1.1       root      160:                        // 通常描画
1.1.1.6   root      161:                        if (modq.Dequeue(&modify)) {
                    162:                                // 更新ブロック数を数える (統計用)
                    163:                                last_mod_blocks = modify.n_dirty;
                    164:                                total_mod_blocks += last_mod_blocks;
                    165:                                if (__predict_false(modify.invalidate2)) {
                    166:                                        total_invalidate2++;
                    167:                                }
1.1       root      168: 
1.1.1.6   root      169:                                // レンダラを駆動する。
                    170:                                // out_dirty は前回 UI に通知した後一度でも更新があれば true。
                    171:                                render_time.Start();
                    172:                                out_dirty |= RenderMain();
                    173:                                render_time.Stop();
                    174:                                render_exec++;
                    175:                        }
                    176: 
                    177:                        if (out_dirty) {
1.1.1.8 ! root      178:                                uint64 rtime = syncer->GetRealTime();
1.1.1.6   root      179:                                if (rtime >= next_refresh_rtime) {
                    180:                                        UIMessage::Post(UIMessage::RENDER);
                    181:                                        next_refresh_rtime = rtime + refresh_interval;
                    182:                                        out_dirty = false;
                    183:                                }
1.1       root      184:                        }
                    185:                }
                    186:        }
                    187: }
                    188: 
1.1.1.6   root      189: // スレッドの終了を指示
1.1.1.2   root      190: void
                    191: Renderer::Terminate()
                    192: {
                    193:        std::unique_lock<std::mutex> lock(mtx);
                    194:        request |= REQ_TERMINATE;
                    195:        cv.notify_one();
                    196: }
                    197: 
1.1.1.6   root      198: // 描画更新(通知)間隔を設定
                    199: void
                    200: Renderer::SetRefreshInterval(uint64 t)
                    201: {
                    202:        refresh_interval = t;
                    203: }
                    204: 
                    205: // モニタ更新
                    206: void
                    207: Renderer::MonitorUpdate(Monitor *, TextScreen& screen)
                    208: {
                    209:        int x;
                    210:        int y;
                    211: 
                    212:        screen.Clear();
                    213: 
                    214:        // modify
                    215:        screen.Print(0, 0, "Last Update Region");
1.1.1.8 ! root      216:        const uint8 *m = &modify.bits[0];
        !           217:        for (int i = 0; i < 32; i++) {
        !           218:                char buf[33];
        !           219:                uint8 c;
        !           220:                for (int j = 0; j < 32; j++) {
        !           221:                        if (__predict_false(*m++ != 0)) {
1.1.1.6   root      222:                                c = '*';
                    223:                        } else {
                    224:                                c = '.';
                    225:                        }
                    226:                        buf[j] = c;
                    227:                }
                    228: 
1.1.1.8 ! root      229:                buf[32] = '\0';
        !           230:                screen.Print(0, 1 + i, "%4d:%s", i * 32, buf);
1.1.1.6   root      231:        }
1.1.1.8 ! root      232:        screen.Puts(0, 1, "Y=");
1.1.1.6   root      233: 
                    234:        x = 43;
                    235:        y = 0;
                    236:        uint64 nsec = render_time.Elapsed();
                    237:        screen.Print(x, y++, "RenderTime %3d.%06d sec",
                    238:                (int)(nsec / 1000 / 1000 / 1000),
                    239:                (int)(nsec / 1000) % (1000 * 1000));
                    240: 
                    241:        screen.Print(x, y++, "RenderExec      %9" PRIu64, render_exec);
                    242: 
                    243:        y++;
                    244:        screen.Print(x, y++, "Last Mod Blks   %9d", last_mod_blocks);
                    245:        screen.Print(x, y++, "Total Mod Blks  %9" PRIu64, total_mod_blocks);
                    246:        screen.Print(x, y++, "Total Invalid2  %9" PRIu64, total_invalidate2);
                    247: }
                    248: 
                    249: 
1.1       root      250: //
                    251: // X68030 レンダラ
                    252: //
                    253: 
                    254: // コンストラクタ
                    255: X68030Renderer::X68030Renderer()
                    256: {
                    257:        // XXX とりあえず
                    258:        width = 768;
                    259:        height = 512;
                    260: }
                    261: 
                    262: // デストラクタ
                    263: X68030Renderer::~X68030Renderer()
                    264: {
                    265: }
                    266: 
                    267: // 画面合成
                    268: bool
                    269: X68030Renderer::RenderMain()
                    270: {
                    271:        // 今はテキスト画面のみを合成バッファに直接描いている
1.1.1.8 ! root      272:        return planevram->Render(bitmap, modify);
1.1       root      273: }
                    274: 
1.1.1.6   root      275: 
1.1       root      276: //
                    277: // LUNA レンダラ
                    278: //
                    279: 
                    280: // コンストラクタ
                    281: LunaRenderer::LunaRenderer()
                    282: {
                    283:        width = 1280;
                    284:        height = 1024;
                    285: }
                    286: 
                    287: // デストラクタ
                    288: LunaRenderer::~LunaRenderer()
                    289: {
                    290: }
                    291: 
                    292: // 画面合成
                    293: bool
                    294: LunaRenderer::RenderMain()
                    295: {
1.1.1.8 ! root      296:        return planevram->Render(bitmap, modify);
        !           297: }
        !           298: 
        !           299: 
        !           300: //
        !           301: // NEWS レンダラ
        !           302: //
        !           303: 
        !           304: // コンストラクタ
        !           305: NewsRenderer::NewsRenderer()
        !           306: {
        !           307:        // XXX サポートしてない
        !           308:        width = 640;
        !           309:        height = 480;
        !           310: }
        !           311: 
        !           312: // デストラクタ
        !           313: NewsRenderer::~NewsRenderer()
        !           314: {
        !           315: }
        !           316: 
        !           317: // 画面合成
        !           318: bool
        !           319: NewsRenderer::RenderMain()
        !           320: {
        !           321:        return false;
1.1.1.6   root      322: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.