Annotation of nono/vm/renderer.cpp, revision 1.1.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.