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

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: {
1.1.1.12! root       39:        size_t devlen = 0x20'0000;      // XXX とりあえず
1.1.1.10  root       40:        mem.reset(new(std::nothrow) uint8[devlen]);
                     41:        if ((bool)mem == false) {
1.1.1.12! root       42:                warnx("Could not allocate %zu bytes at %s", devlen, __method__);
1.1.1.10  root       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.