diff --git a/Aerofoil/GpSystemServices_Win32.cpp b/Aerofoil/GpSystemServices_Win32.cpp index ad1302d..1da5a3d 100644 --- a/Aerofoil/GpSystemServices_Win32.cpp +++ b/Aerofoil/GpSystemServices_Win32.cpp @@ -144,6 +144,11 @@ bool GpSystemServices_Win32::IsTextInputObstructive() const return false; } +bool GpSystemServices_Win32::IsFullscreenPreferred() const +{ + return !m_isTouchscreenSimulation; +} + unsigned int GpSystemServices_Win32::GetCPUCount() const { SYSTEM_INFO sysInfo; diff --git a/Aerofoil/GpSystemServices_Win32.h b/Aerofoil/GpSystemServices_Win32.h index 795fc87..e48c263 100644 --- a/Aerofoil/GpSystemServices_Win32.h +++ b/Aerofoil/GpSystemServices_Win32.h @@ -31,6 +31,7 @@ public: bool IsTouchscreen() const override; bool IsUsingMouseAsTouch() const override; bool IsTextInputObstructive() const override; + bool IsFullscreenPreferred() const override; unsigned int GetCPUCount() const override; void SetTextInputEnabled(bool isEnabled) override; bool IsTextInputEnabled() const override; diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp index 4e39693..f7083ee 100644 --- a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp @@ -265,6 +265,11 @@ bool GpSystemServices_Android::IsTextInputObstructive() const return true; } +bool GpSystemServices_Android::IsFullscreenPreferred() const +{ + return true; +} + unsigned int GpSystemServices_Android::GetCPUCount() const { return SDL_GetCPUCount(); diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h index 3e5c535..52bc820 100644 --- a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h @@ -19,6 +19,7 @@ public: bool IsTouchscreen() const override; bool IsUsingMouseAsTouch() const override; bool IsTextInputObstructive() const override; + bool IsFullscreenPreferred() const override; unsigned int GetCPUCount() const override; void SetTextInputEnabled(bool isEnabled) override; bool IsTextInputEnabled() const override; diff --git a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp index c853f00..ee194b1 100644 --- a/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp +++ b/AerofoilSDL/GpDisplayDriver_SDL_GL2.cpp @@ -1215,7 +1215,7 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties m_bgColor[3] = 1.f; // Stupid hack to detect mobile... - m_isFullScreenDesired = m_properties.m_systemServices->IsTouchscreen() && !m_properties.m_systemServices->IsUsingMouseAsTouch(); + m_isFullScreenDesired = m_properties.m_systemServices->IsFullscreenPreferred(); const intmax_t periodNum = std::chrono::high_resolution_clock::period::num; const intmax_t periodDen = std::chrono::high_resolution_clock::period::den; diff --git a/ApplicationResourcePatches/PICT/1303.bmp b/ApplicationResourcePatches/PICT/1303.bmp new file mode 100644 index 0000000..e7d71e6 Binary files /dev/null and b/ApplicationResourcePatches/PICT/1303.bmp differ diff --git a/ApplicationResourcePatches/manifest.json b/ApplicationResourcePatches/manifest.json index 145c787..8a1722d 100644 --- a/ApplicationResourcePatches/manifest.json +++ b/ApplicationResourcePatches/manifest.json @@ -15,6 +15,7 @@ "PICT/1300.bmp" : "ApplicationResourcePatches/PICT/1300.bmp", "PICT/1301.bmp" : "ApplicationResourcePatches/PICT/1301.bmp", "PICT/1302.bmp" : "ApplicationResourcePatches/PICT/1302.bmp", + "PICT/1303.bmp" : "ApplicationResourcePatches/PICT/1303.bmp", "PICT/1971.bmp" : "ApplicationResourcePatches/PICT/1971.bmp", "PICT/1972.bmp" : "ApplicationResourcePatches/PICT/1972.bmp", "PICT/1973.bmp" : "ApplicationResourcePatches/PICT/1973.bmp", diff --git a/GpApp/Main.cpp b/GpApp/Main.cpp index 20d5553..85d108a 100644 --- a/GpApp/Main.cpp +++ b/GpApp/Main.cpp @@ -12,6 +12,7 @@ #include "Environ.h" #include "FontFamily.h" #include "GpRenderedFontMetrics.h" +#include "IGpMutex.h" #include "IGpThreadEvent.h" #include "IGpDisplayDriver.h" #include "IGpSystemServices.h" @@ -37,7 +38,7 @@ #include - +int loadScreenWindowPhase; int loadScreenRingStep; WindowPtr loadScreenWindow; Rect loadScreenProgressBarRect; @@ -249,7 +250,7 @@ void ReadInPrefs (void) doComplainDialogs = true; IGpDisplayDriver *displayDriver = PLDrivers::GetDisplayDriver(); - if (!displayDriver->IsFullScreen()) + if (PLDrivers::GetSystemServices()->IsFullscreenPreferred() != displayDriver->IsFullScreen()) displayDriver->RequestToggleFullScreen(0); modulePrefs.Dispose(); @@ -371,18 +372,171 @@ void StepLoadScreenRing() Rect ringDestRect = Rect::Create(8, 8, 24, 24); Rect ringSrcRect = Rect::Create(0, 0, 16, 16) + Point::Create((loadScreenRingStep / loadScreenStepGranularity) * 16, 0); + if (loadScreenWindowPhase == 0) + { + ringDestRect = Rect::Create(0, 0, 64, 64); + + const int progression = (loadScreenRingStep / loadScreenStepGranularity); + ringSrcRect = Rect::Create(0, 0, 64, 64) + Point::Create((progression % 6) * 64, (progression / 6) * 64); + } + CopyBits(*loadScreenRingSurface->m_port.GetPixMap(), *loadScreenWindow->GetDrawSurface()->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy); loadScreenWindow->GetDrawSurface()->m_port.SetDirty(PortabilityLayer::QDPortDirtyFlag_Contents); } } + +void CreateLoadScreenWindow(int phase) +{ + if (loadScreenRingSurface) + { + DisposeGWorld(loadScreenRingSurface); + loadScreenRingSurface = nullptr; + } + + if (loadScreenWindow) + { + PortabilityLayer::WindowManager::GetInstance()->DestroyWindow(loadScreenWindow); + loadScreenWindow = nullptr; + } + + if (phase == 0) + { + static const int kLoadScreenHeight = 64; + static const int kLoadScreenWidth = 64; + static const int kLoadRingResource = 1303; + + ForceSyncFrame(); + PLSysCalls::Sleep(1); + + THandle loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast(); + BitmapImage *loadRingImage = *loadRingImageH; + + DrawSurface *loadRingSurface = nullptr; + Rect loadRingRect = loadRingImage->GetRect(); + loadRingRect.right *= 2; + loadRingRect.bottom *= 2; + CreateOffScreenGWorld(&loadRingSurface, &loadRingRect); + loadRingSurface->DrawPicture(loadRingImageH, loadRingRect); + + int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2; + int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2; + + + const Rect loadScreenRect = Rect::Create(lsY, lsX, lsY + kLoadScreenHeight, lsX + kLoadScreenWidth); + const Rect loadScreenLocalRect = Rect::Create(0, 0, loadScreenRect.Height(), loadScreenRect.Width()); + + PortabilityLayer::WindowDef def = PortabilityLayer::WindowDef::Create(loadScreenRect, PortabilityLayer::WindowStyleFlags::kBorderless, true, 0, 0, PSTR("")); + + loadScreenWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(def); + PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(loadScreenWindow, PL_GetPutInFrontWindowPtr()); + + DrawSurface *surface = loadScreenWindow->GetDrawSurface(); + PortabilityLayer::ResolveCachingColor blackColor(StdColors::Black()); + + surface->FillRect(loadScreenLocalRect, blackColor); + + loadScreenProgressBarRect = Rect::Create(0, 0, 0, 0); + loadScreenProgress = 0; + + Rect ringDestRect = Rect::Create(0, 0, 64, 64); + Rect ringSrcRect = Rect::Create(0, 0, 64, 64); + CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy); + + loadRingImageH.Dispose(); + + loadScreenRingSurface = loadRingSurface; + } + else if (phase == 1) + { + static const int kLoadScreenHeight = 32; + static const int kLoadRingResource = 1302; + + int kLoadScreenWidth = 296; + PLPasStr loadingText = PSTR("Loading..."); + + if (!isPrefsLoaded) + { + loadingText = PSTR("Getting some things ready..."); + kLoadScreenWidth = 440; + } + + ForceSyncFrame(); + PLSysCalls::Sleep(1); + + THandle loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast(); + BitmapImage *loadRingImage = *loadRingImageH; + + DrawSurface *loadRingSurface = nullptr; + Rect loadRingRect = loadRingImage->GetRect(); + CreateOffScreenGWorld(&loadRingSurface, &loadRingRect); + loadRingSurface->DrawPicture(loadRingImageH, loadRingRect); + + int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2; + int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2; + + + const Rect loadScreenRect = Rect::Create(lsY, lsX, lsY + kLoadScreenHeight, lsX + kLoadScreenWidth); + const Rect loadScreenLocalRect = Rect::Create(0, 0, loadScreenRect.Height(), loadScreenRect.Width()); + + PortabilityLayer::WindowDef def = PortabilityLayer::WindowDef::Create(loadScreenRect, PortabilityLayer::WindowStyleFlags::kAlert, true, 0, 0, PSTR("")); + + loadScreenWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(def); + PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(loadScreenWindow, PL_GetPutInFrontWindowPtr()); + + DrawSurface *surface = loadScreenWindow->GetDrawSurface(); + PortabilityLayer::ResolveCachingColor blackColor(StdColors::Black()); + PortabilityLayer::ResolveCachingColor whiteColor(StdColors::White()); + + surface->FillRect(loadScreenLocalRect, whiteColor); + + PortabilityLayer::WindowManager::GetInstance()->FlickerWindowIn(loadScreenWindow, 32); + + PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true); + int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2; + surface->DrawString(Point::Create(4 + 16 + 8, textY), loadingText, blackColor, font); + + static const int32_t loadBarPadding = 16; + static const int32_t loadBarHeight = 10; + int32_t loadBarStartX = static_cast(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + 8 + loadBarPadding; + int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding; + + loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - loadBarHeight) / 2, loadBarStartX, (loadScreenLocalRect.Height() + loadBarHeight) / 2, loadBarEndX); + + PortabilityLayer::ResolveCachingColor partialFillColor(PortabilityLayer::RGBAColor::Create(255, 255, 204, 255)); + surface->FrameRect(loadScreenProgressBarRect, blackColor); + surface->FillRect(loadScreenProgressBarRect.Inset(1, 1), partialFillColor); + + Rect ringDestRect = Rect::Create(8, 8, 24, 24); + Rect ringSrcRect = Rect::Create(0, 0, 16, 16); + CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy); + + loadRingImageH.Dispose(); + + loadScreenRingSurface = loadRingSurface; + } +} + void StepLoadScreen(int steps) { if (loadScreenWindow) { - Rect loadScreenProgressBarFillRect = loadScreenProgressBarRect.Inset(1, 1); + static const int kLoadScreenPhaseSwitchBreakpoint = 20; + int oldProgress = loadScreenProgress; - int loadScreenMax = 32; + + if (loadScreenProgress + steps >= kLoadScreenPhaseSwitchBreakpoint && loadScreenWindowPhase == 0) + { + loadScreenWindowPhase = 1; + CreateLoadScreenWindow(loadScreenWindowPhase); + + // Reset old progress since the progress bar was redrawn + oldProgress = 0; + } + + const Rect loadScreenProgressBarFillRect = loadScreenProgressBarRect.Inset(1, 1); + + int loadScreenMax = 42; loadScreenProgress = loadScreenProgress + steps; if (loadScreenProgress > loadScreenMax) loadScreenProgress = loadScreenMax; @@ -411,72 +565,12 @@ void InitLoadingWindow() if (!thisMac.isTouchscreen) return; - static const int kLoadScreenHeight = 32; - static const int kLoadRingResource = 1302; + if (isPrefsLoaded) + loadScreenWindowPhase = 1; + else + loadScreenWindowPhase = 0; - int kLoadScreenWidth = 296; - PLPasStr loadingText = PSTR("Loading..."); - - if (!isPrefsLoaded) - { - loadingText = PSTR("Getting some things ready..."); - kLoadScreenWidth = 440; - } - - ForceSyncFrame(); - PLSysCalls::Sleep(1); - - THandle loadRingImageH = PortabilityLayer::ResourceManager::GetInstance()->GetAppResource('PICT', kLoadRingResource).StaticCast(); - BitmapImage *loadRingImage = *loadRingImageH; - - DrawSurface *loadRingSurface = nullptr; - Rect loadRingRect = loadRingImage->GetRect(); - CreateOffScreenGWorld(&loadRingSurface, &loadRingRect); - loadRingSurface->DrawPicture(loadRingImageH, loadRingRect); - - int32_t lsX = (thisMac.fullScreen.Width() - kLoadScreenWidth) / 2; - int32_t lsY = (thisMac.fullScreen.Height() - kLoadScreenHeight) / 2; - - - const Rect loadScreenRect = Rect::Create(lsY, lsX, lsY + kLoadScreenHeight, lsX + kLoadScreenWidth); - const Rect loadScreenLocalRect = Rect::Create(0, 0, loadScreenRect.Height(), loadScreenRect.Width()); - - PortabilityLayer::WindowDef def = PortabilityLayer::WindowDef::Create(loadScreenRect, PortabilityLayer::WindowStyleFlags::kAlert, true, 0, 0, PSTR("")); - - loadScreenWindow = PortabilityLayer::WindowManager::GetInstance()->CreateWindow(def); - PortabilityLayer::WindowManager::GetInstance()->PutWindowBehind(loadScreenWindow, PL_GetPutInFrontWindowPtr()); - - DrawSurface *surface = loadScreenWindow->GetDrawSurface(); - PortabilityLayer::ResolveCachingColor blackColor(StdColors::Black()); - PortabilityLayer::ResolveCachingColor whiteColor(StdColors::White()); - - surface->FillRect(loadScreenLocalRect, whiteColor); - - PortabilityLayer::WindowManager::GetInstance()->FlickerWindowIn(loadScreenWindow, 32); - - PortabilityLayer::RenderedFont *font = GetApplicationFont(18, PortabilityLayer::FontFamilyFlag_None, true); - int32_t textY = (kLoadScreenHeight + font->GetMetrics().m_ascent) / 2; - surface->DrawString(Point::Create(4+16+8, textY), loadingText, blackColor, font); - - static const int32_t loadBarPadding = 16; - static const int32_t loadBarHeight = 10; - int32_t loadBarStartX = static_cast(font->MeasureString(loadingText.UChars(), loadingText.Length())) + 4 + 16 + 8 + loadBarPadding; - int32_t loadBarEndX = loadScreenLocalRect.right - loadBarPadding; - - loadScreenProgressBarRect = Rect::Create((loadScreenLocalRect.Height() - loadBarHeight) / 2, loadBarStartX, (loadScreenLocalRect.Height() + loadBarHeight) / 2, loadBarEndX); - loadScreenProgress = 0; - - PortabilityLayer::ResolveCachingColor partialFillColor(PortabilityLayer::RGBAColor::Create(255, 255, 204, 255)); - surface->FrameRect(loadScreenProgressBarRect, blackColor); - surface->FillRect(loadScreenProgressBarRect.Inset(1, 1), partialFillColor); - - Rect ringDestRect = Rect::Create(8, 8, 24, 24); - Rect ringSrcRect = Rect::Create(0, 0, 16, 16); - CopyBits(*loadRingSurface->m_port.GetPixMap(), *surface->m_port.GetPixMap(), &ringSrcRect, &ringDestRect, srcCopy); - - loadRingImageH.Dispose(); - - loadScreenRingSurface = loadRingSurface; + CreateLoadScreenWindow(loadScreenWindowPhase); } enum PreloadFontCategory @@ -542,12 +636,12 @@ void PreloadSingleFont (const PreloadFontSpec &spec) } } -void PreloadThreadFunc(void *context) +void PreloadFontThreadFunc(void *context) { PreloadFontWorkSlot *wSlot = static_cast(context); PreloadSingleFont(*wSlot->m_spec); - ++wSlot->m_singleJobCompleted; + wSlot->m_singleJobCompleted.fetch_add(1, std::memory_order_release); wSlot->m_completedEvent->Signal(); } @@ -555,6 +649,9 @@ void PreloadFonts() { static PreloadFontSpec specs[] = { + // First entry should be the one needed to show the load screen + { FontCategory_Application, 18, PortabilityLayer::FontFamilyFlag_None, true }, + { FontCategory_System, 9, PortabilityLayer::FontFamilyFlag_Bold, true }, { FontCategory_System, 10, PortabilityLayer::FontFamilyFlag_Bold, true }, { FontCategory_System, 12, PortabilityLayer::FontFamilyFlag_None, true }, @@ -563,7 +660,6 @@ void PreloadFonts() { FontCategory_Application, 9, PortabilityLayer::FontFamilyFlag_None, true }, { FontCategory_Application, 12, PortabilityLayer::FontFamilyFlag_Bold, true }, { FontCategory_Application, 14, PortabilityLayer::FontFamilyFlag_Bold, true }, - { FontCategory_Application, 18, PortabilityLayer::FontFamilyFlag_None, true }, { FontCategory_Application, 40, PortabilityLayer::FontFamilyFlag_None, true }, { FontCategory_Handwriting, 24, PortabilityLayer::FontFamilyFlag_None, true }, { FontCategory_Handwriting, 48, PortabilityLayer::FontFamilyFlag_None, true }, @@ -588,7 +684,7 @@ void PreloadFonts() { if (slot.m_queued) { - if (slot.m_singleJobCompleted.load(std::memory_order_relaxed) != 0) + if (slot.m_singleJobCompleted.load(std::memory_order_acquire) != 0) { slot.m_completedEvent->Wait(); slot.m_queued = false; @@ -603,9 +699,9 @@ void PreloadFonts() if (queuedSpecs < numFontSpecs) { slot.m_queued = true; - slot.m_singleJobCompleted.store(0); slot.m_spec = specs + queuedSpecs; - slot.m_workerThread->AsyncExecuteTask(PreloadThreadFunc, &slot); + slot.m_singleJobCompleted.store(0, std::memory_order_release); + slot.m_workerThread->AsyncExecuteTask(PreloadFontThreadFunc, &slot); queuedSpecs++; } @@ -616,6 +712,55 @@ void PreloadFonts() } } +struct PreloadAATableSpec +{ + PortabilityLayer::RGBAColor m_color; + bool m_isTone; +}; + +struct PreloadAATableWorkSlot +{ + IGpThreadEvent *m_completedEvent; + IGpMutex *m_mutex; + PortabilityLayer::WorkerThread *m_workerThread; + std::atomic m_singleJobCompleted; + const PreloadAATableSpec *m_spec; + bool m_queued; + + PreloadAATableWorkSlot(); + ~PreloadAATableWorkSlot(); +}; + +PreloadAATableWorkSlot::PreloadAATableWorkSlot() + : m_completedEvent(nullptr) + , m_workerThread(nullptr) + , m_spec(nullptr) + , m_queued(false) +{ +} + +PreloadAATableWorkSlot::~PreloadAATableWorkSlot() +{ + if (m_workerThread) + m_workerThread->Destroy(); +} + + +void PreloadAATableThreadFunc(void *context) +{ + PreloadAATableWorkSlot *wSlot = static_cast(context); + + PortabilityLayer::StandardPalette *sp = PortabilityLayer::StandardPalette::GetInstance(); + + if (wSlot->m_spec->m_isTone) + sp->GetCachedToneAATable(wSlot->m_spec->m_color.r, wSlot->m_mutex); + else + sp->GetCachedPaletteAATable(wSlot->m_spec->m_color, wSlot->m_mutex); + + wSlot->m_singleJobCompleted.fetch_add(1, std::memory_order_release); + wSlot->m_completedEvent->Signal(); +} + void PreloadAATables() { PortabilityLayer::StandardPalette *sp = PortabilityLayer::StandardPalette::GetInstance(); @@ -630,15 +775,119 @@ void PreloadAATables() PortabilityLayer::RGBAColor::Create(204, 102, 51, 255), }; - const size_t numPreloads = sizeof(preloadColors) / sizeof(preloadColors[0]); + const size_t numPalettePreloads = sizeof(preloadColors) / sizeof(preloadColors[0]); + const size_t maxTonePreloads = numPalettePreloads * 3; - for (size_t i = 0; i < numPreloads; i++) + PreloadAATableSpec specs[numPalettePreloads + maxTonePreloads]; + for (size_t i = 0; i < numPalettePreloads; i++) { - sp->GetCachedPaletteAATable(preloadColors[i]); - sp->GetCachedToneAATable(preloadColors[i].r); - sp->GetCachedToneAATable(preloadColors[i].g); - sp->GetCachedToneAATable(preloadColors[i].b); - StepLoadScreen(1); + specs[i].m_color = preloadColors[i]; + specs[i].m_isTone = false; + } + + size_t numTonePreloads = 0; + for (size_t i = 0; i < numPalettePreloads; i++) + { + const uint8_t rgb[3] = { preloadColors[i].r, preloadColors[i].g, preloadColors[i].b }; + + for (int ch = 0; ch < 3; ch++) + { + uint8_t tone = rgb[ch]; + + bool toneAlreadyQueued = false; + for (size_t j = 0; j < numTonePreloads; j++) + { + if (specs[numPalettePreloads + j].m_color.r == tone) + { + toneAlreadyQueued = true; + break; + } + } + + if (!toneAlreadyQueued) + { + PreloadAATableSpec &spec = specs[i + numTonePreloads]; + numTonePreloads++; + + spec.m_color = PortabilityLayer::RGBAColor::Create(tone, tone, tone, 255); + spec.m_isTone = true; + } + } + } + + PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); + + const int numAASpecs = numPalettePreloads + numTonePreloads; + + unsigned int cpus = PLDrivers::GetSystemServices()->GetCPUCount(); + if (cpus < 2) + { + for (size_t i = 0; i < numAASpecs; i++) + { + PreloadAATableThreadFunc(specs + i); + StepLoadScreen(1); + } + } + else + { + cpus -= 1; + + int queuedSpecs = 0; + int completedSpecs = 0; + + PreloadAATableWorkSlot *slots = static_cast(mm->Alloc(sizeof(PreloadAATableWorkSlot) * cpus)); + + IGpMutex *mutex = PLDrivers::GetSystemServices()->CreateMutex(); + + for (unsigned int i = 0; i < cpus; i++) + { + PreloadAATableWorkSlot *slot = new (slots + i) PreloadAATableWorkSlot(); + slot->m_workerThread = PortabilityLayer::WorkerThread::Create(); + slot->m_completedEvent = PLDrivers::GetSystemServices()->CreateThreadEvent(true, false); + slot->m_mutex = mutex; + } + + while (completedSpecs < numAASpecs) + { + for (unsigned int i = 0; i < cpus; i++) + { + PreloadAATableWorkSlot &slot = slots[i]; + + if (slot.m_queued) + { + if (slot.m_singleJobCompleted.load(std::memory_order_acquire) != 0) + { + slot.m_completedEvent->Wait(); + slot.m_queued = false; + completedSpecs++; + + StepLoadScreen(1); + } + } + + if (!slot.m_queued) + { + if (queuedSpecs < numAASpecs) + { + slot.m_queued = true; + slot.m_spec = specs + queuedSpecs; + slot.m_singleJobCompleted.store(0, std::memory_order_release); + slot.m_workerThread->AsyncExecuteTask(PreloadAATableThreadFunc, &slot); + + queuedSpecs++; + } + } + } + + StepLoadScreenRing(); + Delay(1, nullptr); + } + + for (unsigned int i = 0; i < cpus; i++) + slots[i].~PreloadAATableWorkSlot(); + + mm->Release(slots); + mutex->Destroy(); } } @@ -681,8 +930,9 @@ int gpAppMain() FlushResolutionChange(); InitLoadingWindow(); StepLoadScreen(2); - PreloadFonts(); StepLoadScreen(2); PreloadAATables(); + assert(isPrefsLoaded || loadScreenWindowPhase == 0); + PreloadFonts(); StepLoadScreen(2); #if defined COMPILEDEMO copyGood = true; diff --git a/GpCommon/IGpSystemServices.h b/GpCommon/IGpSystemServices.h index dfdec0b..a9f0d2c 100644 --- a/GpCommon/IGpSystemServices.h +++ b/GpCommon/IGpSystemServices.h @@ -28,6 +28,7 @@ public: virtual void Beep() const = 0; virtual bool IsTouchscreen() const = 0; virtual bool IsUsingMouseAsTouch() const = 0; + virtual bool IsFullscreenPreferred() const = 0; virtual bool IsTextInputObstructive() const = 0; virtual unsigned int GetCPUCount() const = 0; virtual void SetTextInputEnabled(bool isEnabled) = 0; diff --git a/PortabilityLayer/QDStandardPalette.cpp b/PortabilityLayer/QDStandardPalette.cpp index 173d7b3..1a6a096 100644 --- a/PortabilityLayer/QDStandardPalette.cpp +++ b/PortabilityLayer/QDStandardPalette.cpp @@ -1,4 +1,5 @@ #include "QDStandardPalette.h" +#include "IGpMutex.h" #include @@ -232,15 +233,22 @@ namespace PortabilityLayer return &ms_instance; } - const AntiAliasTable &StandardPalette::GetCachedPaletteAATable(const RGBAColor &color) + const AntiAliasTable &StandardPalette::GetCachedPaletteAATable(const RGBAColor &color, IGpMutex *mutex) { uint8_t rgb[3] = { color.r, color.g, color.b }; + if (mutex) + mutex->Lock(); + for (size_t i = 0; i < m_numCachedPaletteTables; i++) { const CachedPaletteTableEntry &entry = m_cachedPaletteTables[i]; if (entry.m_rgb[0] == rgb[0] && entry.m_rgb[1] == rgb[1] && entry.m_rgb[2] == rgb[2]) + { + if (mutex) + mutex->Unlock(); return entry.m_aaTable; + } } if (m_numCachedPaletteTables == kMaxCachedPaletteTables) @@ -250,18 +258,29 @@ namespace PortabilityLayer entry.m_rgb[0] = rgb[0]; entry.m_rgb[1] = rgb[1]; entry.m_rgb[2] = rgb[2]; + + if (mutex) + mutex->Unlock(); + entry.m_aaTable.GenerateForPalette(color, m_colors, 256, true); return entry.m_aaTable; } - const AntiAliasTable &StandardPalette::GetCachedToneAATable(uint8_t tone) + const AntiAliasTable &StandardPalette::GetCachedToneAATable(uint8_t tone, IGpMutex *mutex) { + if (mutex) + mutex->Lock(); + for (size_t i = 0; i < m_numCachedToneTables; i++) { const CachedToneTableEntry &entry = m_cachedToneTables[i]; if (entry.m_tone == tone) + { + if (mutex) + mutex->Unlock(); return entry.m_aaTable; + } } if (m_numCachedToneTables == kMaxCachedToneTables) @@ -269,6 +288,10 @@ namespace PortabilityLayer CachedToneTableEntry &entry = m_cachedToneTables[m_numCachedToneTables++]; entry.m_tone = tone; + + if (mutex) + mutex->Unlock(); + entry.m_aaTable.GenerateForSimpleScale(tone, true); return entry.m_aaTable; diff --git a/PortabilityLayer/QDStandardPalette.h b/PortabilityLayer/QDStandardPalette.h index f4c21d7..d43df32 100644 --- a/PortabilityLayer/QDStandardPalette.h +++ b/PortabilityLayer/QDStandardPalette.h @@ -3,6 +3,8 @@ #include "AntiAliasTable.h" #include "RGBAColor.h" +struct IGpMutex; + namespace PortabilityLayer { struct AntiAliasTable; @@ -21,8 +23,8 @@ namespace PortabilityLayer uint8_t MapColorLUT(uint8_t r, uint8_t g, uint8_t b) const; uint8_t MapColorLUT(const RGBAColor &color) const; - const AntiAliasTable &GetCachedPaletteAATable(const RGBAColor &color); - const AntiAliasTable &GetCachedToneAATable(uint8_t tone); + const AntiAliasTable &GetCachedPaletteAATable(const RGBAColor &color, IGpMutex *mutex = nullptr); + const AntiAliasTable &GetCachedToneAATable(uint8_t tone, IGpMutex *mutex = nullptr); static StandardPalette *GetInstance();