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

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2018 [email protected]
        !             4: //
        !             5: 
        !             6: #include "object.h"
        !             7: #include "bitmap.h"
        !             8: #include "bt454.h"
        !             9: #include "renderer.h"
        !            10: #include "tvram.h"
        !            11: 
        !            12: Renderer *gRenderer;
        !            13: 
        !            14: static void *renderer_run(void *);
        !            15: 
        !            16: // コンストラクタ
        !            17: Renderer::Renderer()
        !            18: {
        !            19:        logname = "renderer";
        !            20:        devname = "Render";
        !            21: }
        !            22: 
        !            23: // デストラクタ
        !            24: Renderer::~Renderer()
        !            25: {
        !            26:        // imagebuf の所有権は持っていないので解放不要。
        !            27: 
        !            28:        // スレッド終了を指示
        !            29:        std::unique_lock<std::mutex> lock(mtx);
        !            30:        request |= REQ_TERMINATE;
        !            31:        cv.notify_one();
        !            32: }
        !            33: 
        !            34: bool
        !            35: Renderer::Init()
        !            36: {
        !            37:        // レンダリングスレッド起動
        !            38:        pthread_t th;
        !            39:        pthread_create(&th, NULL, renderer_run, NULL);
        !            40: 
        !            41:        return true;
        !            42: }
        !            43: 
        !            44: bool
        !            45: Renderer::PowerOff()
        !            46: {
        !            47:        if (imagebuf) {
        !            48:                // レンダリングスレッドに指示
        !            49:                std::unique_lock<std::mutex> lock(mtx);
        !            50:                request |= REQ_REND_POWEROFF;
        !            51:                cv.notify_one();
        !            52:        }
        !            53: 
        !            54:        return true;
        !            55: }
        !            56: 
        !            57: // バッファとコールバックを指定する。
        !            58: // 引数 buf と callback はどちらも NULL であってはならない。
        !            59: // これは画面を必要とする wx 側から呼ばれる。CLI では呼ばれない。
        !            60: void
        !            61: Renderer::SetBuf(uint8 *buf, void (*callback)(void))
        !            62: {
        !            63:        assert(buf);
        !            64:        assert(callback);
        !            65: 
        !            66:        imagebuf = buf;
        !            67:        refresh_callback = callback;
        !            68: }
        !            69: 
        !            70: // 画面合成処理 (CRTC とかから呼ばれる部分)
        !            71: // 今は一画面単位で合成を行なっている。ラスター云々は未対応。
        !            72: // 画面合成を行うかどうかとか、レンダリングスレッドに指示を出すかとか
        !            73: // どこら辺までを呼び出し元とこっちが分担するかは未定。
        !            74: void
        !            75: Renderer::Render()
        !            76: {
        !            77:        // CLI 版なら何もしない。
        !            78:        if (imagebuf == NULL) {
        !            79:                return;
        !            80:        }
        !            81: 
        !            82:        // スケジューラ都合による間引きとかがあればここらへんで評価?
        !            83:        // XXX どっちのスレッドでやるか
        !            84: 
        !            85:        // レンダリングスレッドに指示
        !            86:        std::unique_lock<std::mutex> lock(mtx);
        !            87:        request |= REQ_REND_NORMAL;
        !            88:        cv.notify_one();
        !            89: }
        !            90: 
        !            91: // レンダリングスレッドのエントリポイント
        !            92: void *
        !            93: renderer_run(void *dummy)
        !            94: {
        !            95:        pthread_setname_np("Renderer");
        !            96:        pthread_detach(pthread_self());
        !            97: 
        !            98:        gRenderer->ThreadRun();
        !            99:        return NULL;
        !           100: }
        !           101: 
        !           102: // レンダリングスレッド
        !           103: void
        !           104: Renderer::ThreadRun()
        !           105: {
        !           106:        for (;;) {
        !           107:                uint32 req;
        !           108: 
        !           109:                // 何か起きるまで待つ
        !           110:                {
        !           111:                        std::unique_lock<std::mutex> lock(mtx);
        !           112:                        cv.wait(lock, [&] { return (request != 0); });
        !           113:                        req = request;
        !           114:                        request = 0;
        !           115:                }
        !           116: 
        !           117:                if ((req & REQ_TERMINATE)) {
        !           118:                        // 終了するので、他のフラグは無視
        !           119:                        break;
        !           120: 
        !           121:                } else if ((req & REQ_REND_POWEROFF)) {
        !           122:                        // 電源オフ時の描画 (通常描画フラグは無視)
        !           123: 
        !           124:                        // 電源オフされると画面を灰色にする。
        !           125:                        // 黒でもいいけど、電源オンで黒いままなのと区別したい。
        !           126:                        memset(imagebuf, 0x70, width * height * BPP);
        !           127:                        // ウィンドウに通知
        !           128:                        refresh_callback();
        !           129: 
        !           130:                } else if ((req & REQ_REND_NORMAL)) {
        !           131:                        // 通常描画
        !           132: 
        !           133:                        // レンダラを駆動して
        !           134:                        if (RenderMain()) {
        !           135:                                // 更新があればウィンドウに通知
        !           136:                                refresh_callback();
        !           137:                        }
        !           138:                }
        !           139:        }
        !           140: }
        !           141: 
        !           142: //
        !           143: // X68030 レンダラ
        !           144: //
        !           145: 
        !           146: // コンストラクタ
        !           147: X68030Renderer::X68030Renderer()
        !           148: {
        !           149:        // XXX とりあえず
        !           150:        width = 768;
        !           151:        height = 512;
        !           152: }
        !           153: 
        !           154: // デストラクタ
        !           155: X68030Renderer::~X68030Renderer()
        !           156: {
        !           157: }
        !           158: 
        !           159: // 画面合成
        !           160: bool
        !           161: X68030Renderer::RenderMain()
        !           162: {
        !           163:        assert(imagebuf);
        !           164: 
        !           165:        // 今はテキスト画面のみを合成バッファに直接描いている
        !           166:        return gTVRAM->Render(imagebuf);
        !           167: }
        !           168: 
        !           169: //
        !           170: // LUNA レンダラ
        !           171: //
        !           172: 
        !           173: // コンストラクタ
        !           174: LunaRenderer::LunaRenderer()
        !           175: {
        !           176:        width = 1280;
        !           177:        height = 1024;
        !           178: }
        !           179: 
        !           180: // デストラクタ
        !           181: LunaRenderer::~LunaRenderer()
        !           182: {
        !           183: }
        !           184: 
        !           185: // 画面合成
        !           186: bool
        !           187: LunaRenderer::RenderMain()
        !           188: {
        !           189:        const uint8 *pal;
        !           190:        const uint32 *plane0;
        !           191:        std::atomic<uint8> *dirty;
        !           192:        int hscroll;
        !           193:        int vscroll;
        !           194:        uint8 *dst0;
        !           195:        bool updated;
        !           196: 
        !           197:        assert(imagebuf);
        !           198:        dst0 = imagebuf;
        !           199: 
        !           200:        // パレット取得
        !           201:        pal = gBT454->GetHostPalette();
        !           202: 
        !           203:        // ビットマップ
        !           204:        gBitmap->GetRFCNT(&hscroll, &vscroll);
        !           205:        const uint8 *mem = gBitmap->GetBuf();
        !           206:        dirty = gBitmap->GetDirty();
        !           207: 
        !           208:        updated = false;
        !           209: 
        !           210:        // dirty は VRAM への書き込みがあれば常に 1 にする。
        !           211:        // レンダリング時に dirty が 1 なら 2 にしてレンダリング。
        !           212:        // レンダリング終了時に dirty が 2 なら 0 に戻す。
        !           213:        // これによりレンダリング中に VRAM への書き込みがあれば次回描画される。
        !           214: 
        !           215:        // sy はメモリ上の Y 座標
        !           216:        // dy はレンダラ画面の Y 座標 (RFCNT のラスタカウンタを考慮)
        !           217: 
        !           218:        // XXX とりあえず1プレーン
        !           219:        plane0 = (uint32 *)mem;
        !           220:        int sy = vscroll;
        !           221:        for (int dy = 0; dy < height; dst0 += width * BPP, dy++, sy++) {
        !           222:                sy &= 0x3ff;
        !           223: 
        !           224:                if (atomic_cas_8(&dirty[sy], 1, 2) == 1) {
        !           225:                        uint8 *dst = dst0;
        !           226:                        // sx はメモリ上の X オフセット (ロングワード単位)
        !           227:                        // dx はレンダラ画面の X オフセット (ロングワード単位)
        !           228:                        // XXX 水平オフセットが仕様以上の時の挙動は未実装
        !           229: 
        !           230:                        int sx = (sy * 2048 + hscroll) / 32;
        !           231:                        int shift = (hscroll & 31);
        !           232:                        for (int dx = 0; dx < width / 32; dx++, sx++) {
        !           233:                                uint32 p0 = plane0[sx];
        !           234:                                if (shift) {
        !           235:                                        p0 = (p0 << shift) | (plane0[sx + 1] >> (32 - shift));
        !           236:                                }
        !           237: 
        !           238:                                // 1ロングワードの横 32bit が横 32dot に相当
        !           239:                                for (int j = 0; j < 32; j++) {
        !           240:                                        // 1bpp の時 P1,P2,P3 分はプルアップされて %1 に
        !           241:                                        // なっているっぽいので、実質 #14 か #15 ということ。
        !           242:                                        uint c = 14;
        !           243:                                        // カラーコード(パレット番号)を作成
        !           244:                                        if ((p0 & 0x80000000U)) c |= 1;
        !           245:                                        p0 <<= 1;
        !           246: 
        !           247:                                        *dst++ = pal[c * 4 + 0];
        !           248:                                        *dst++ = pal[c * 4 + 1];
        !           249:                                        *dst++ = pal[c * 4 + 2];
        !           250:                                }
        !           251:                        }
        !           252: 
        !           253:                        // 2の時だけ0に戻す
        !           254:                        atomic_cas_8(&dirty[sy], 2, 0);
        !           255:                        updated = true;
        !           256:                }
        !           257:        }
        !           258: 
        !           259:        return updated;
        !           260: }

unix.superglobalmegacorp.com

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