--- nono/vm/planevram.cpp 2026/04/29 17:05:17 1.1.1.2 +++ nono/vm/planevram.cpp 2026/04/29 17:05:29 1.1.1.4 @@ -11,9 +11,6 @@ #include "planevram.h" #include "mybswap.h" -#if defined(__x86_64__) -#include -#endif // コンストラクタ PlaneVRAMDevice::PlaneVRAMDevice(int width_, int height_) @@ -56,7 +53,7 @@ PlaneVRAMDevice::InitDeptable() // %0000000a'0000000b'0000000c'0000000d'0000000e'0000000f'0000000g'0000000h // の64ビットに伸張する。 // (8ビットを各バイトの最下位ビットに対応させる) - for (int i = 0; i < 256; i++) { + for (uint i = 0; i < 256; i++) { uint64 res = 0; for (int bit = 0; bit < 8; bit++) { int n = bit * 8; @@ -84,27 +81,28 @@ PlaneVRAMDevice::ClearDirty() std::fill(dirty.begin(), dirty.end(), 0); } -// 更新情報を取得。 +// 更新情報を取得。更新がなければ false を返す。 // VM スレッドから呼ばれる。 -ModifyInfo -PlaneVRAMDevice::GetModify() const +bool +PlaneVRAMDevice::GetModify(ModifyInfo *mod) const { - ModifyInfo mod; - memcpy(&mod.bits[0], &dirty[0], mod.bits.size()); - // TODO: 互換性のために n_dirty 計算。廃止するかも。 + memcpy(&mod->bits[0], &dirty[0], mod->bits.size()); + + // 一つでも更新があれば dirty。 + mod->dirty = false; for (int i = 0; i < dirty.size(); i++) { if (dirty[i]) { - mod.n_dirty++; + mod->dirty = true; + break; } } - - return mod; + return mod->dirty; } // 画面合成。 // レンダラスレッドから呼ばれる。 bool -PlaneVRAMDevice::Render(BitmapRGB& bitmap, const ModifyInfo& modify) +PlaneVRAMDevice::Render(BitmapRGBX& dst, const ModifyInfo& modify) { bool updated = false; @@ -115,9 +113,9 @@ PlaneVRAMDevice::Render(BitmapRGB& bitma } // composite に更新があるか(update)、 - // 無条件に更新するか(invalidate2) なら bitmap を更新。 + // 無条件に更新するか(invalidate2) なら dst を更新。 if (updated || modify.invalidate2) { - RenderCompositeToRGB(bitmap, modify); + RenderCompositeToRGBX(dst, modify); updated = true; } @@ -129,15 +127,15 @@ PlaneVRAMDevice::Render(BitmapRGB& bitma void PlaneVRAMDevice::RenderVRAMToComposite(const ModifyInfo& modify) { - const int width = composite.GetWidth(); - const int height = composite.GetHeight(); - const int planesz = (width / 8) * height; + const uint width = composite.GetWidth(); + const uint height = composite.GetHeight(); + const uint planesz = (width / 8) * height; // 1bpp はパレット的にはほぼ 4bpp と同じ扱いになる。 const int nplane4 = (nplane == 1) ? 4 : nplane; // テキスト合成画面を描く - for (int y = 0; y < height; y++) { + for (uint y = 0; y < height; y++) { uint8 mod = modify.bits[y]; if (mod == 0) { continue; @@ -145,9 +143,9 @@ PlaneVRAMDevice::RenderVRAMToComposite(c const uint32 *src = (const uint32 *)&mem[0]; src += y * width / 32; - uint64 *dst = (uint64 *)composite.GetPtr(0, y); + uint64 *dst = (uint64 *)composite.GetRowPtr(y); - for (int x = 0; x < width / 32; x++) { + for (uint x = 0; x < width / 32; x++) { std::array data; // VRAM はホストエンディアンに関係なく 32bit で読み込んだ @@ -173,7 +171,7 @@ PlaneVRAMDevice::RenderVRAMToComposite(c data[2] = 0xffffffff; data[3] = 0xffffffff; } else { - int offset = planesz / sizeof(uint32); + uint offset = planesz / sizeof(uint32); for (int plane = 0; plane < nplane; plane++) { data[plane] = bswap32(src[plane * offset]); } @@ -209,15 +207,15 @@ PlaneVRAMDevice::RenderVRAMToComposite(c } } -// composite 画面とパレット情報から RGB 画面を合成する。 +// composite 画面とパレット情報から RGBX 画面を合成する。 // modify は composite 上での変更箇所を示している。 // レンダラスレッドから呼ばれる。 void -PlaneVRAMDevice::RenderCompositeToRGB(BitmapRGB& bitmap, +PlaneVRAMDevice::RenderCompositeToRGBX(BitmapRGBX& dst, const ModifyInfo& modify) { - const int width = bitmap.GetWidth(); - const int height = bitmap.GetHeight(); + const uint width = dst.GetWidth(); + const uint height = dst.GetHeight(); // view_mod は表示領域 view における更新ラスタ BitmapI8 view(width, height); @@ -259,7 +257,7 @@ PlaneVRAMDevice::RenderCompositeToRGB(Bi continue; } - uint8 *v = view.GetPtr(0, y); + uint8 *v = view.GetRowPtr(y); uint8 *c = composite.GetPtr(xscroll, sy); if (xscroll + view.GetWidth() <= composite.GetWidth()) { memcpy(v, c, view.GetWidth()); @@ -269,96 +267,12 @@ PlaneVRAMDevice::RenderCompositeToRGB(Bi memcpy(v, c, len1); v += len1; int sy2 = GetWrapY(sy); - c = composite.GetPtr(0, sy2); + c = composite.GetRowPtr(sy2); int len2 = view.GetWidth() - len1; memcpy(v, c, len2); } } - // view (I8) を Bitmap (RGB) に展開する - for (int y = 0; y < view_mod.size(); y++) { - if (view_mod[y] == 0) { - continue; - } - - const uint8 *s8 = view.GetPtr(0, y); - uint32 *d = (uint32 *)bitmap.GetPtr(0, y); - - const uint32 *s = (const uint32 *)s8; - const uint32 *send = (const uint32 *)(s8 + view.GetWidth()); - for (; s < send;) { - // s は BitmapI8 なのでビッグエンディアン並びに相当 - -#if defined(__AVX2__) && !defined(NO_AVX) // オプション -mavx2 が必要 - // 35.1msec - - // 8ピクセルずつ処理する - - // idx0 = $00000000'00000000'I7I6I5I4'I3I2I1I0 - __m128i idx0 = _mm_loadl_epi64((const __m128i *)s); - s += 2; - - // idx = $000000I7'000000I6'000000I5'000000I4' - // 000000I3'000000I2'000000I1'000000I0 - __m256i idx = _mm256_cvtepu8_epi32(idx0); - - // 8個の 32bit インデックスから XBGR を取得 - // c = $00B7G7R7'00B6G6R6'00B5G5R5'00B4G4R4' - // 00B3G3R3'00B2G2R2'00B1G1R1'00B0G0R0 - __m256i c = _mm256_i32gather_epi32( - (const int *)palette, idx, 4); - - // 256bit リニアに使えれば下詰めで済んだんだが、 - // 上位 128bit と下位 128bit をまたいでシャッフルは - // 出来なくて、かつこの後のストアは連続領域への - // 書き込みになるので、中央でつなげておく。うーん。 - // c = $00000000'B7G7R7B6'G6R6B5G5'R5B4G4R4' - // B3G3R3B2'G2R2B1G1'R1B0G0R0'00000000 - __m256i shuff = _mm256_set_epi8( - -1,-1,-1,-1, 14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0, - 14,13,12,10, 9, 8, 6, 5, 4, 2, 1, 0, -1,-1,-1,-1 - ); - __m256i res = _mm256_shuffle_epi8(c, shuff); - - // 先頭(下位)と末尾(上位)の 32bit ずつを除いたところを - // 書き出す。 - __m256i mask = _mm256_set_epi32( - 0, -1, -1, -1, -1, -1, -1, 0 - ); - _mm256_maskstore_epi32((int *)(d - 1), mask, res); - d += 6; -#else - // 46.5msec - - // 4ピクセルずつ処理する - - uint32 cc4 = *s++; - // 左側ピクセルが下位バイトになるよう並び替える - // (le32toh() はビッグエンディアンなら bswap32 の意) - cc4 = le32toh(cc4); - - // 4ピクセルをそれぞれ xBGR32 に変換 - uint32 c0 = palette[ cc4 & 0xff].xbgr; - uint32 c1 = palette[(cc4 >> 8) & 0xff].xbgr; - uint32 c2 = palette[(cc4 >> 16) & 0xff].xbgr; - uint32 c3 = palette[ cc4 >> 24 ].xbgr; - - // xBGR32 4つ(16バイト)を RGB24 3つ(12バイト)に変換して - // ロングワードで書き出す。 - // c0 = $x0B0G0R0 - // c1 = $x1B1G1R1 - // c2 = $x2B2G2R2 - // c3 = $x3B3G3R3 - // - // d[0] = $00B0G0R0 | $R1000000 = $R1B0G0R0 - // d[1] = $0000B1G1 | $G2R20000 = $G2R2B1G1 - // d[2] = $000000B2 | $B3G3R300 = $B3G3R3B2 - - // (le32toh() はビッグエンディアンなら bswap32 の意) - *d++ = le32toh((c0 ) | (c1 << 24)); - *d++ = le32toh((c1 >> 8) | (c2 << 16)); - *d++ = le32toh((c2 >> 16) | (c3 << 8)); -#endif - } - } + // view (I8) を Bitmap (RGBX) に展開する + dst.DrawBitmapI8Raster(view, palette, &view_mod[0]); }