Annotation of nono/vm/gvram.cpp, revision 1.1.1.11

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: 
                      7: //
                      8: // GVRAM
                      9: //
1.1.1.6   root       10: 
1.1       root       11: // GVRAM はワード単位でホストバイトオーダ配置なので、
                     12: // バイトアクセス時は HB() マクロを使用のこと。
                     13: 
1.1.1.6   root       14: #include "gvram.h"
1.1.1.11! root       15: #include "event.h"
        !            16: #include "textscreen.h"
1.1.1.6   root       17: #include "videoctlr.h"
                     18: 
1.1.1.8   root       19: // InsideOut p.135
1.1.1.11! root       20: /*static*/ const busdata
        !            21: GVRAMDevice::wait = busdata::Wait(9 * 40_nsec);
1.1.1.8   root       22: 
1.1.1.6   root       23: // コンストラクタ
1.1       root       24: GVRAMDevice::GVRAMDevice()
1.1.1.7   root       25:        : inherited(OBJ_GVRAM)
1.1       root       26: {
1.1.1.11! root       27:        composite.Create(1024, 1024);
1.1       root       28: }
                     29: 
1.1.1.6   root       30: // デストラクタ
1.1       root       31: GVRAMDevice::~GVRAMDevice()
                     32: {
                     33: }
                     34: 
1.1.1.10  root       35: // 初期化
                     36: bool
                     37: GVRAMDevice::Init()
                     38: {
                     39:        uint devlen = 0x20'0000;        // XXX とりあえず
                     40:        mem.reset(new(std::nothrow) uint8[devlen]);
                     41:        if ((bool)mem == false) {
                     42:                warnx("Cannot allocate %u bytes at %s", devlen, __method__);
                     43:                return false;
                     44:        }
                     45: 
1.1.1.11! root       46:        videoctlr = GetVideoCtlrDevice();
        !            47: 
        !            48:        // 加工済みグラフィックパレットを取得。
        !            49:        palette = &(videoctlr->GetHostPalette())[0];
        !            50: 
1.1.1.10  root       51:        return true;
                     52: }
                     53: 
1.1.1.11! root       54: void
        !            55: GVRAMDevice::ResetHard(bool poweron)
        !            56: {
        !            57:        // XXX ここ?
        !            58:        Invalidate();
        !            59: }
        !            60: 
        !            61: // 全画面の更新フラグを立てる。
        !            62: void
        !            63: GVRAMDevice::Invalidate()
        !            64: {
        !            65:        dirty.line.set();
        !            66: }
        !            67: 
1.1.1.9   root       68: inline uint32
                     69: GVRAMDevice::Decoder(uint32 addr) const
1.1       root       70: {
1.1.1.9   root       71:        return addr - baseaddr;
1.1       root       72: }
                     73: 
1.1.1.8   root       74: busdata
1.1.1.9   root       75: GVRAMDevice::Read(busaddr addr)
1.1       root       76: {
1.1.1.9   root       77:        uint32 offset = Decoder(addr.Addr());
1.1.1.8   root       78:        busdata data;
1.1.1.9   root       79: 
                     80:        data = *(uint16 *)&mem[offset & ~1U];
1.1.1.8   root       81:        data |= wait;
1.1.1.9   root       82:        data |= BusData::Size2;
1.1.1.8   root       83:        return data;
1.1       root       84: }
                     85: 
1.1.1.8   root       86: busdata
1.1.1.9   root       87: GVRAMDevice::Write(busaddr addr, uint32 data)
1.1       root       88: {
1.1.1.9   root       89:        uint32 offset = Decoder(addr.Addr());
                     90:        uint32 reqsize = addr.GetSize();
                     91:        uint32 datasize = std::min(2 - (offset & 1U), reqsize);
                     92:        data >>= (reqsize - datasize) * 8;
                     93: 
1.1.1.11! root       94:        // 現状 1024x1024 (4bit) しか対応していない。
        !            95:        if (__predict_false(datasize == 1)) {
        !            96:                if ((offset & 1) != 0) {
        !            97:                        mem[HB(offset)] = data & 0x0f;
        !            98:                }
1.1.1.9   root       99:        } else {
1.1.1.11! root      100:                *(uint16 *)&mem[offset] = data & 0x0f;
1.1.1.9   root      101:        }
1.1.1.11! root      102:        SetDirty(offset);
1.1.1.9   root      103: 
                    104:        busdata r = wait;
                    105:        r |= busdata::Size(datasize);
                    106:        return r;
1.1       root      107: }
                    108: 
1.1.1.8   root      109: busdata
1.1.1.9   root      110: GVRAMDevice::Peek1(uint32 addr)
1.1       root      111: {
1.1.1.9   root      112:        uint32 offset = Decoder(addr);
                    113:        return mem[HB(offset)];
1.1       root      114: }
1.1.1.11! root      115: 
        !           116: bool
        !           117: GVRAMDevice::Poke1(uint32 addr, uint32 data)
        !           118: {
        !           119:        if ((int32)data >= 0) {
        !           120:                uint32 offset = Decoder(addr);
        !           121:                // 現状 1024x1024 モードしか対応していないため
        !           122:                // 有効なのはワード中下位4ビット。
        !           123:                if ((offset & 1) != 0) {
        !           124:                        mem[HB(offset)] = data & 0x0f;
        !           125:                        // この場合も画面を更新する。
        !           126:                        SetDirty(offset);
        !           127:                }
        !           128:        }
        !           129:        return true;
        !           130: }
        !           131: 
        !           132: // offset の位置に対応する更新フラグを立てる。
        !           133: // offset はページ先頭からのバイトオフセット。
        !           134: inline void
        !           135: GVRAMDevice::SetDirty(uint32 offset)
        !           136: {
        !           137:        // GVRAM (1024x1024 モード) は
        !           138:        // 横 1024 ドット(2048バイト) x 縦 1024 ドット。
        !           139:        //
        !           140:        //                1                               0
        !           141:        //        4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
        !           142:        //       +-------------------+---------------------+
        !           143:        // GVRAM |  Y座標 (1024dot)  |   X座標 (1024word)  |
        !           144:        //       +-------------------+---------------------+
        !           145:        //       :                   :
        !           146:        //       +-------------------+
        !           147:        //       |                   |
        !           148:        //       +-------------------+
        !           149:        //        9 8 7 6 5 4 3 2 1 0
        !           150: 
        !           151:        // 更新フラグはラスタ単位
        !           152:        uint y = offset >> 11;
        !           153:        dirty.line.set(y);
        !           154: }
        !           155: 
        !           156: // 画面更新する必要があるか。
        !           157: // VM スレッドで呼ばれる。
        !           158: bool
        !           159: GVRAMDevice::Snap()
        !           160: {
        !           161:        bool update_needed;
        !           162: 
        !           163:        // 更新 (dirty) があれば pending に重ねる。
        !           164:        {
        !           165:                std::lock_guard<std::mutex> lock(mtx);
        !           166:                pending.line |= dirty.line;
        !           167:                dirty.line.reset();
        !           168: 
        !           169:                if (__predict_false(dirty.invalidate2)) {
        !           170:                        pending.invalidate2 = true;
        !           171:                        dirty.invalidate2 = false;
        !           172:                }
        !           173: 
        !           174:                update_needed = pending.line.any() || pending.invalidate2;
        !           175:        }
        !           176: 
        !           177:        return update_needed;
        !           178: }
        !           179: 
        !           180: // 画面合成。
        !           181: // レンダラスレッドで VideoCtlr から呼ばれる。
        !           182: // dst を更新すれば true を返す。
        !           183: bool
        !           184: GVRAMDevice::Render(BitmapRGBX& dst)
        !           185: {
        !           186:        bool updated = false;
        !           187: 
        !           188:        // ローカルにコピー。
        !           189:        ModifyInfo modified;
        !           190:        {
        !           191:                std::lock_guard<std::mutex> lock(mtx);
        !           192:                modified.line = pending.line;
        !           193:                modified.invalidate2 = pending.invalidate2;
        !           194:                pending.line.reset();
        !           195:                pending.invalidate2 = false;
        !           196:        }
        !           197: 
        !           198:        // GVRAM に更新があれば composite を更新。
        !           199:        if (modified.line.any()) {
        !           200:                Render1024ToComposite(modified.line);
        !           201:                updated = true;
        !           202:        }
        !           203: 
        !           204:        // composite に更新があるか(updated)、
        !           205:        // 無条件に更新するか(modified.invalidate2) なら dst を更新。
        !           206:        if (updated || modified.invalidate2) {
        !           207:                RenderCompositeToRGBX(dst, modified);
        !           208:                updated = true;
        !           209:        }
        !           210: 
        !           211:        return updated;
        !           212: }
        !           213: 
        !           214: // GVRAM (1024x1024、16色モード) から composite 画面を合成する。
        !           215: // レンダラスレッドから呼ばれる。
        !           216: void
        !           217: GVRAMDevice::Render1024ToComposite(const bitset1024& modified)
        !           218: {
        !           219:        constexpr uint xend = 1024;
        !           220:        constexpr uint yend = 1024;
        !           221:        for (uint y = 0; y < yend; y++) {
        !           222:                if (__predict_true(modified.test(y) == false)) {
        !           223:                        continue;
        !           224:                }
        !           225: 
        !           226:                const uint16 *src = (const uint16 *)&mem[0];
        !           227:                src += y * 1024;
        !           228:                uint8 *dst = (uint8 *)composite.GetRowPtr(y);
        !           229:                for (uint x = 0; x < xend; x++) {
        !           230:                        *dst++ = *src++;
        !           231:                }
        !           232:        }
        !           233: }
        !           234: 
        !           235: void
        !           236: GVRAMDevice::RenderCompositeToRGBX(BitmapRGBX& dst,
        !           237:        const ModifyInfo& modified)
        !           238: {
        !           239:        dst.DrawBitmapI8(0, 0, composite, palette);
        !           240: }
        !           241: 
        !           242: // (x, y) 位置のピクセル情報を screen に出力。(ビットマップモニタの情報欄)
        !           243: void
        !           244: GVRAMDevice::UpdateInfo(TextScreen& screen, int x, int y) const
        !           245: {
        !           246:        screen.Clear();
        !           247: 
        !           248:        // 0         1         2         3         4         5         6
        !           249:        // 012345678901234567890123456789012345678901234567890123456789012345
        !           250:        // X=1023 Y=1023: ColorCode=$d
        !           251: 
        !           252:        screen.Puts(0, 0, "X=     Y=");
        !           253:        if (x >= 0) {
        !           254:                const uint16 *mem16 = (const uint16 *)&mem[0];
        !           255:                uint16 cc = mem16[y * 1024 + x];
        !           256:                screen.Print(2, 0, "%4d Y=%4d Colorcode=$%x", x, y, cc);
        !           257:        }
        !           258: }

unix.superglobalmegacorp.com

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