From afc3083b3e4c7dfd55335caf57dcf2c5f6ef0625 Mon Sep 17 00:00:00 2001 From: sukibaby <163092272+sukibaby@users.noreply.github.com> Date: Sat, 4 Jan 2025 08:09:30 -0800 Subject: [PATCH] (Win32 refresh) LoadingWindow_Win32 Speed up the loading window. SetPixelV is slow. No perceptible difference in loading window behavior, but is faster. The goal here is to alleviate the case where the loading window is the bottleneck when loading songs on a fast computer. --- .../LoadingWindow/LoadingWindow_Win32.cpp | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/arch/LoadingWindow/LoadingWindow_Win32.cpp b/src/arch/LoadingWindow/LoadingWindow_Win32.cpp index d66f77f3c2..bd88cd28f5 100644 --- a/src/arch/LoadingWindow/LoadingWindow_Win32.cpp +++ b/src/arch/LoadingWindow/LoadingWindow_Win32.cpp @@ -27,22 +27,18 @@ static HBITMAP g_hBitmap = nullptr; /* Load a RageSurface into a GDI surface. */ static HBITMAP LoadWin32Surface( const RageSurface *pSplash, HWND hWnd ) { - RageSurface *s = CreateSurface( pSplash->w, pSplash->h, 32, - 0xFF000000, 0x00FF0000, 0x0000FF00, 0 ); - RageSurfaceUtils::Blit( pSplash, s , -1, -1 ); + RageSurface *s = CreateSurface( pSplash->w, pSplash->h, 24, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0 ); + RageSurfaceUtils::Blit( pSplash, s, -1, -1 ); /* Resize the splash image to fit the dialog. Stretch to fit horizontally, * maintaining aspect ratio. */ - { - RECT r; - GetClientRect( hWnd, &r ); - - int iWidth = r.right; - float fRatio = (float) iWidth / s->w; - int iHeight = std::lrint( s->h * fRatio ); - - RageSurfaceUtils::Zoom( s, iWidth, iHeight ); - } + RECT r; + GetClientRect(hWnd, &r); + int iWidth = r.right; + float fRatio = static_cast(iWidth) / s->w; + int iHeight = static_cast(std::round(s->h * fRatio)); + RageSurfaceUtils::Zoom(s, iWidth, iHeight); HDC hScreen = GetDC(nullptr); ASSERT_M( hScreen != nullptr, werr_ssprintf(GetLastError(), "hScreen") ); @@ -53,22 +49,34 @@ static HBITMAP LoadWin32Surface( const RageSurface *pSplash, HWND hWnd ) HDC BitmapDC = CreateCompatibleDC( hScreen ); SelectObject( BitmapDC, bitmap ); - /* This is silly, but simple. We only do this once, on a small image. */ + // Top-down DIB + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof(bmi)); + bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); + bmi.bmiHeader.biWidth = s->w; + bmi.bmiHeader.biHeight = -s->h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + std::vector buffer(s->w * s->h * 3); for( int y = 0; y < s->h; ++y ) { - unsigned const char *line = ((unsigned char *) s->pixels) + (y * s->pitch); for( int x = 0; x < s->w; ++x ) { - unsigned const char *data = line + (x*s->format->BytesPerPixel); - - SetPixelV( BitmapDC, x, y, RGB( data[3], data[2], data[1] ) ); + uint8_t* srcPixel = s->pixels + y * s->pitch + x * s->format->BytesPerPixel; + uint8_t* dstPixel = &buffer[(y * s->w + x) * 3]; + dstPixel[0] = srcPixel[2]; // Blue + dstPixel[1] = srcPixel[1]; // Green + dstPixel[2] = srcPixel[0]; // Red } } - SelectObject( BitmapDC, nullptr ); - DeleteObject( BitmapDC ); + SetDIBits(BitmapDC, bitmap, 0, s->h, buffer.data(), &bmi, DIB_RGB_COLORS); - ReleaseDC( nullptr, hScreen ); + SelectObject(BitmapDC, nullptr); + DeleteDC(BitmapDC); + ReleaseDC(nullptr, hScreen); delete s; return bitmap; @@ -190,11 +198,11 @@ void LoadingWindow_Win32::SetText( RString sText ) for( unsigned i = 0; i < 3; ++i ) { if( text[i] == asMessageLines[i] ) - continue; - text[i] = asMessageLines[i]; - - HWND hwndItem = ::GetDlgItem( hwnd, msgid[i] ); - ::SetWindowText( hwndItem, ConvertUTF8ToACP(asMessageLines[i]).c_str() ); + { + text[i] = asMessageLines[i]; + HWND hwndItem = ::GetDlgItem(hwnd, msgid[i]); + ::SetWindowText(hwndItem, ConvertUTF8ToACP(asMessageLines[i]).c_str()); + } } }