3DS: Fix fake mosaic performance

This commit is contained in:
Anders Jenbo 2025-07-05 01:08:53 +02:00
parent fa049eadb6
commit aaf465e7d6
2 changed files with 54 additions and 40 deletions

View File

@ -642,8 +642,14 @@ int GetColorIndexWithLocality(int p_col, int p_row)
void MxTransitionManager::FakeMosaicTransition() void MxTransitionManager::FakeMosaicTransition()
{ {
static LPDIRECTDRAWSURFACE g_fakeTranstionSurface = nullptr;
if (m_animationTimer == 16) { if (m_animationTimer == 16) {
m_animationTimer = 0; m_animationTimer = 0;
if (g_fakeTranstionSurface) {
g_fakeTranstionSurface->Release();
g_fakeTranstionSurface = nullptr;
}
EndTransition(TRUE); EndTransition(TRUE);
return; return;
} }
@ -662,12 +668,33 @@ void MxTransitionManager::FakeMosaicTransition()
} }
} }
if (!g_fakeTranstionSurface) {
DDSURFACEDESC mainDesc = {};
mainDesc.dwSize = sizeof(mainDesc);
if (m_ddSurface->GetSurfaceDesc(&mainDesc) != DD_OK) {
return;
}
DDSURFACEDESC tempDesc = {};
tempDesc.dwSize = sizeof(tempDesc);
tempDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
tempDesc.dwWidth = 64;
tempDesc.dwHeight = 48;
tempDesc.ddpfPixelFormat = mainDesc.ddpfPixelFormat;
tempDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
HRESULT hr = MVideoManager()->GetDirectDraw()->CreateSurface(&tempDesc, &g_fakeTranstionSurface, nullptr);
if (hr != DD_OK || !g_fakeTranstionSurface) {
return;
}
}
DDSURFACEDESC ddsd = {}; DDSURFACEDESC ddsd = {};
ddsd.dwSize = sizeof(ddsd); ddsd.dwSize = sizeof(ddsd);
HRESULT res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); HRESULT res = g_fakeTranstionSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if (res == DDERR_SURFACELOST) { if (res == DDERR_SURFACELOST) {
m_ddSurface->Restore(); g_fakeTranstionSurface->Restore();
res = m_ddSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); res = g_fakeTranstionSurface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
} }
if (res == DD_OK) { if (res == DD_OK) {
@ -694,50 +721,33 @@ void MxTransitionManager::FakeMosaicTransition()
} }
for (MxS32 row = 0; row < 48; row++) { for (MxS32 row = 0; row < 48; row++) {
MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); int paletteIndex = GetColorIndexWithLocality(col, row);
MxS32 yStart = 10 * row;
int paletteIndex = GetColorIndexWithLocality(xShift / 10, row);
const MxU8* color = g_palette[paletteIndex]; const MxU8* color = g_palette[paletteIndex];
for (MxS32 y = 0; y < 10; y++) { MxS32 xShift = (m_randomShift[row] + col) % 64;
MxU8* dest = (MxU8*) ddsd.lpSurface + (yStart + y) * ddsd.lPitch + xShift * bytesPerPixel; MxU8* dest = (MxU8*) ddsd.lpSurface + row * ddsd.lPitch + xShift * bytesPerPixel;
switch (bytesPerPixel) {
case 1: switch (bytesPerPixel) {
memset(dest, paletteIndex, 10); case 1:
break; *dest = paletteIndex;
case 2: { break;
MxU32 pixel = RGB555_CREATE(color[2], color[1], color[0]); case 2:
MxU16* p = (MxU16*) dest; *((MxU16*) dest) = RGB555_CREATE(color[2], color[1], color[0]);
for (MxS32 i = 0; i < 10; i++) { break;
p[i] = pixel; default:
} *((MxU32*) dest) = RGB8888_CREATE(color[2], color[1], color[0], 255);
break; break;
}
default: {
MxU32 pixel = RGB8888_CREATE(color[2], color[1], color[0], 255);
MxU32* p = (MxU32*) dest;
for (MxS32 i = 0; i < 10; i++) {
p[i] = pixel;
}
break;
}
}
} }
} }
} }
SetupCopyRect(&ddsd); SetupCopyRect(&ddsd);
m_ddSurface->Unlock(ddsd.lpSurface); g_fakeTranstionSurface->Unlock(ddsd.lpSurface);
if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) { RECT srcRect = {0, 0, 64, 48};
VideoManager() m_ddSurface->Blt(&g_fullScreenRect, g_fakeTranstionSurface, &srcRect, DDBLT_WAIT, NULL);
->GetDisplaySurface()
->GetDirectDrawSurface1()
->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT);
}
m_animationTimer++;
} }
m_animationTimer++;
} }

View File

@ -121,6 +121,9 @@ static SDL_Surface* ConvertAndResizeSurface(SDL_Surface* original, bool isUI, fl
return SDL_ConvertSurface(original, SDL_PIXELFORMAT_RGBA8888); return SDL_ConvertSurface(original, SDL_PIXELFORMAT_RGBA8888);
} }
scaleX = std::min(scaleX, 1.0f);
scaleY = std::min(scaleY, 1.0f);
int scaledW = static_cast<int>(original->w * scaleX); int scaledW = static_cast<int>(original->w * scaleX);
int scaledH = static_cast<int>(original->h * scaleY); int scaledH = static_cast<int>(original->h * scaleY);
@ -136,8 +139,9 @@ static SDL_Surface* ConvertAndResizeSurface(SDL_Surface* original, bool isUI, fl
SDL_BlitSurface(original, nullptr, padded, nullptr); SDL_BlitSurface(original, nullptr, padded, nullptr);
} }
else { else {
SDL_ScaleMode scaleMode = (scaleX >= 1.0f && scaleY >= 1.0f) ? SDL_SCALEMODE_NEAREST : SDL_SCALEMODE_LINEAR;
SDL_Rect dstRect = {0, 0, scaledW, scaledH}; SDL_Rect dstRect = {0, 0, scaledW, scaledH};
SDL_BlitSurfaceScaled(original, nullptr, padded, &dstRect, SDL_SCALEMODE_LINEAR); SDL_BlitSurfaceScaled(original, nullptr, padded, &dstRect, scaleMode);
} }
return padded; return padded;