From 947ddf865fa9a1d85a75384fe3e4012e2aed7b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 12 Sep 2025 12:57:52 -0600 Subject: [PATCH 1/3] Extract some duplicated code into a pngSave function --- Common/Data/Format/PNGLoad.cpp | 35 +++++++++++++++++++++++ Common/Data/Format/PNGLoad.h | 3 ++ Common/Render/AtlasGen.cpp | 26 +---------------- Common/Render/AtlasGen.h | 1 - Core/Screenshot.cpp | 52 +++------------------------------- GPU/Common/TextureReplacer.cpp | 34 +++------------------- 6 files changed, 47 insertions(+), 104 deletions(-) diff --git a/Common/Data/Format/PNGLoad.cpp b/Common/Data/Format/PNGLoad.cpp index 83128f018e..51ebd5d9ac 100644 --- a/Common/Data/Format/PNGLoad.cpp +++ b/Common/Data/Format/PNGLoad.cpp @@ -5,6 +5,7 @@ #include "Common/Data/Format/PNGLoad.h" #include "Common/Log.h" +#include "Common/File/FileUtil.h" // *image_data_ptr should be deleted with free() // return value of 1 == success. @@ -131,3 +132,37 @@ bool PNGHeaderPeek::IsValidPNGHeader() const { } return true; } + +bool pngSave(const Path &filename, const void *buffer, int w, int h, int bytesPerPixel) { + png_image png{}; + png.version = PNG_IMAGE_VERSION; + png.format = bytesPerPixel == 3 ? PNG_FORMAT_RGB : PNG_FORMAT_RGBA; + png.width = w; + png.height = h; + const int row_stride = w * bytesPerPixel; + + FILE *fp = File::OpenCFile(filename, "wb"); + if (!fp) { + ERROR_LOG(Log::IO, "Unable to open png file for writing: %s", filename.c_str()); + return false; + } + + int result = png_image_write_to_stdio(&png, fp, 0, buffer, row_stride, nullptr); + + if (png.warning_or_error >= 2) { + ERROR_LOG(Log::IO, "Saving image to PNG produced errors."); + } + + png_image_free(&png); + fclose(fp); + + if (!result) { + // Should we even do this? + File::Delete(filename); + + ERROR_LOG(Log::IO, "PNG encode failed."); + return false; + } + + return true; +} diff --git a/Common/Data/Format/PNGLoad.h b/Common/Data/Format/PNGLoad.h index 76ab04ee9e..85057d2278 100644 --- a/Common/Data/Format/PNGLoad.h +++ b/Common/Data/Format/PNGLoad.h @@ -3,6 +3,7 @@ #include #include "Common/BitSet.h" +#include "Common/File/Path.h" // *image_data_ptr should be deleted with free() // return value of 1 == success. @@ -31,3 +32,5 @@ struct PNGHeaderPeek { int Width() const { return swap32(be_width); } int Height() const { return swap32(be_height); } }; + +bool pngSave(const Path &filename, const void *buffer, int w, int h, int bytesPerPixel); diff --git a/Common/Render/AtlasGen.cpp b/Common/Render/AtlasGen.cpp index 071fefd607..085fc01204 100644 --- a/Common/Render/AtlasGen.cpp +++ b/Common/Render/AtlasGen.cpp @@ -65,14 +65,6 @@ void Image::copyfrom(const Image &img, int ox, int oy, Effect effect) { } } -void Image::set(int sx, int sy, int ex, int ey, u32 fil) { - for (int y = sy; y < ey; y++) { - for (int x = sx; x < ex; x++) { - dat[y * w + x] = fil; - } - } -} - bool Image::LoadPNG(const char *png_name) { unsigned char *img_data; int w, h; @@ -89,23 +81,7 @@ bool Image::LoadPNG(const char *png_name) { } void Image::SavePNG(const char *png_name) { - // Save PNG - FILE *fil = fopen(png_name, "wb"); - png_structp png_ptr; - png_infop info_ptr; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - assert(png_ptr); - info_ptr = png_create_info_struct(png_ptr); - assert(info_ptr); - png_init_io(png_ptr, fil); - //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); - png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png_ptr, info_ptr); - for (int y = 0; y < height(); y++) { - png_write_row(png_ptr, (png_byte*)(dat.data() + y * w)); - } - png_write_end(png_ptr, NULL); - png_destroy_write_struct(&png_ptr, &info_ptr); + pngSave(Path(png_name), dat.data(), w, h, 4); } void Image::SaveZIM(const char *zim_name, int zim_format) { diff --git a/Common/Render/AtlasGen.h b/Common/Render/AtlasGen.h index ce2db6503e..9fd7ef5736 100644 --- a/Common/Render/AtlasGen.h +++ b/Common/Render/AtlasGen.h @@ -68,7 +68,6 @@ struct Image { } u32 get1(int x, int y) const { return dat[y * w + x]; } void copyfrom(const Image &img, int ox, int oy, Effect effect); - void set(int sx, int sy, int ex, int ey, u32 fil); bool LoadPNG(const char *png_name); void SavePNG(const char *png_name); void SaveZIM(const char *zim_name, int zim_format); diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index f147b78357..2788c91516 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -25,6 +25,7 @@ #include "Common/Data/Convert/ColorConv.h" #include "Common/File/FileUtil.h" #include "Common/File/Path.h" +#include "Common/Data/Format/PNGLoad.h" #include "Common/Log.h" #include "Common/System/System.h" #include "Common/System/Display.h" @@ -38,8 +39,7 @@ // This is used to make non-ASCII paths work for filename. // Technically only needed on Windows. -class JPEGFileStream : public jpge::output_stream -{ +class JPEGFileStream : public jpge::output_stream { public: JPEGFileStream(const Path &filename) { fp_ = File::OpenCFile(filename, "wb"); @@ -101,25 +101,6 @@ static bool WriteScreenshotToJPEG(const Path &filename, int width, int height, i return dst_stream.Valid(); } -static bool WriteScreenshotToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { - FILE *fp = File::OpenCFile(filename, "wb"); - if (!fp) { - ERROR_LOG(Log::IO, "Unable to open screenshot file for writing."); - return false; - } - - if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, row_stride, colormap)) { - fclose(fp); - return true; - } else { - ERROR_LOG(Log::IO, "Screenshot PNG encode failed."); - fclose(fp); - // Should we even do this? - File::Delete(filename); - return false; - } -} - static bool ConvertPixelTo8888RGBA(GPUDebugBufferFormat fmt, u8 &r, u8 &g, u8 &b, u8 &a, const void *buffer, int offset, bool rev) { const u8 *buf8 = (const u8 *)buffer; const u16 *buf16 = (const u16 *)buffer; @@ -383,20 +364,7 @@ ScreenshotResult TakeGameScreenshot(Draw::DrawContext *draw, const Path &filenam bool Save888RGBScreenshot(const Path &filename, ScreenshotFormat fmt, const u8 *bufferRGB888, int w, int h) { if (fmt == ScreenshotFormat::PNG) { - png_image png; - memset(&png, 0, sizeof(png)); - png.version = PNG_IMAGE_VERSION; - png.format = PNG_FORMAT_RGB; - png.width = w; - png.height = h; - bool success = WriteScreenshotToPNG(&png, filename, 0, bufferRGB888, w * 3, nullptr); - png_image_free(&png); - - if (png.warning_or_error >= 2) { - ERROR_LOG(Log::IO, "Saving screenshot to PNG produced errors."); - success = false; - } - return success; + return pngSave(filename, bufferRGB888, w, h, 3); } else if (fmt == ScreenshotFormat::JPG) { jpge::params params; params.m_quality = 90; @@ -407,19 +375,7 @@ bool Save888RGBScreenshot(const Path &filename, ScreenshotFormat fmt, const u8 * } bool Save8888RGBAScreenshot(const Path &filename, const u8 *buffer, int w, int h) { - png_image png{}; - png.version = PNG_IMAGE_VERSION; - png.format = PNG_FORMAT_RGBA; - png.width = w; - png.height = h; - bool success = WriteScreenshotToPNG(&png, filename, 0, buffer, w * 4, nullptr); - png_image_free(&png); - - if (png.warning_or_error >= 2) { - ERROR_LOG(Log::IO, "Saving screenshot to PNG produced errors."); - success = false; - } - return success; + return pngSave(filename, buffer, w, h, 4); } bool Save8888RGBAScreenshot(std::vector &bufferPNG, const u8 *bufferRGBA8888, int w, int h) { diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index b29feeb1e8..ddead376d3 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -25,6 +25,7 @@ #include "ext/xxhash.h" #include "Common/Data/Format/IniFile.h" +#include "Common/Data/Format/PNGLoad.h" #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" #include "Common/File/VFS/DirectoryReader.h" @@ -679,25 +680,6 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, return texture; } -static bool WriteTextureToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { - FILE *fp = File::OpenCFile(filename, "wb"); - if (!fp) { - ERROR_LOG(Log::TexReplacement, "Save texture: Unable to open texture file '%s' for writing.", filename.c_str()); - return false; - } - - if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, row_stride, colormap)) { - fclose(fp); - return true; - } else { - // This shouldn't really happen. - ERROR_LOG(Log::TexReplacement, "Texture PNG encode failed."); - fclose(fp); - remove(filename.c_str()); - return false; - } -} - // We save textures on threadpool tasks since it's a fire-and-forget task, and both I/O and png compression // can be pretty slow. class SaveTextureTask : public Task { @@ -747,19 +729,11 @@ public: // going to write to to .png. saveFilename = saveFilename.WithReplacedExtension(".png"); - png_image png{}; - png.version = PNG_IMAGE_VERSION; - png.format = PNG_FORMAT_RGBA; - png.width = w; - png.height = h; - bool success = WriteTextureToPNG(&png, saveFilename, 0, rgbaData, w * 4, nullptr); - png_image_free(&png); - if (png.warning_or_error >= 2) { + bool success = pngSave(saveFilename, rgbaData, w, h, 4); + if (!success) { ERROR_LOG(Log::TexReplacement, "Saving texture to PNG produced errors."); - } else if (success) { - NOTICE_LOG(Log::TexReplacement, "Saving texture for replacement: %08x / %dx%d in '%s'", replacedInfoHash, w, h, saveFilename.ToVisualString().c_str()); } else { - ERROR_LOG(Log::TexReplacement, "Failed to write '%s'", saveFilename.c_str()); + NOTICE_LOG(Log::TexReplacement, "Saving texture for replacement: %08x / %dx%d in '%s'", replacedInfoHash, w, h, saveFilename.ToVisualString().c_str()); } } }; From daa593bdcbbba721c7a45a6c832640a107902076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 15 Sep 2025 12:42:11 -0600 Subject: [PATCH 2/3] Invert the relationship for loading atlas textures --- Common/UI/Context.cpp | 25 ++++++++++--------------- Common/UI/Context.h | 16 ++++++++++++++++ Common/UI/View.cpp | 6 ++++-- UI/NativeApp.cpp | 36 ++++++++++++++++++++++++++++++++++++ UI/Theme.cpp | 6 +++--- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/Common/UI/Context.cpp b/Common/UI/Context.cpp index 8139441d6a..e4d6335b7f 100644 --- a/Common/UI/Context.cpp +++ b/Common/UI/Context.cpp @@ -42,22 +42,17 @@ void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pi void UIContext::BeginFrame() { frameStartTime_ = time_now_d(); if (!uitexture_) { - uitexture_ = CreateTextureFromFile(draw_, "ui_atlas.zim", ImageFileType::ZIM, false); - if (!fontTexture_) { -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - // Don't bother with loading font_atlas.zim -#else - fontTexture_ = CreateTextureFromFile(draw_, "font_atlas.zim", ImageFileType::ZIM, false); -#endif - if (!fontTexture_) { - // Load the smaller ascii font only, like on Android. For debug ui etc. - fontTexture_ = CreateTextureFromFile(draw_, "asciifont_atlas.zim", ImageFileType::ZIM, false); - if (!fontTexture_) { - WARN_LOG(Log::System, "Failed to load font_atlas.zim or asciifont_atlas.zim"); - } - } - } + AtlasData data = atlasProvider_(draw_, AtlasChoice::General); + uitexture_ = data.texture; + ui_draw2d.SetAtlas(data.atlas); } + + if (!fontTexture_) { + AtlasData data = atlasProvider_(draw_, AtlasChoice::Font); + fontTexture_ = data.texture; + ui_draw2d.SetFontAtlas(data.atlas); + } + uidrawbuffer_->SetCurZ(0.0f); ActivateTopScissor(); } diff --git a/Common/UI/Context.h b/Common/UI/Context.h index 9e6f8969de..ec8582d3ca 100644 --- a/Common/UI/Context.h +++ b/Common/UI/Context.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Common/Math/geom2d.h" #include "Common/Math/lin/vec3.h" @@ -43,6 +44,18 @@ struct UITransform { float alpha; }; +enum class AtlasChoice : int { + General, + Font, +}; + +struct AtlasData { + Atlas *atlas; + Draw::Texture *texture; +}; + +typedef std::function UIAtlasProviderFunc; + class UIContext { public: UIContext(); @@ -112,6 +125,7 @@ public: Bounds TransformBounds(const Bounds &bounds); void SetTheme(const UI::Theme *theme) { this->theme = theme; } + void SetAtlasProvider(UIAtlasProviderFunc func) { atlasProvider_ = func; } private: Draw::DrawContext *draw_ = nullptr; @@ -136,4 +150,6 @@ private: std::vector scissorStack_; std::vector transformStack_; + + UIAtlasProviderFunc atlasProvider_{}; }; diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index 6f882e2a5d..2a732ed66d 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -1833,8 +1833,10 @@ void DrawIconShine(UIContext &dc, const Bounds &bounds, float shine, bool animat dc.Begin(); } const AtlasImage *img = dc.Draw()->GetAtlas()->getImage(ImageID("I_DROP_SHADOW")); - float scale = bounds.w / img->w; - dc.Draw()->DrawImage(ImageID("I_DROP_SHADOW"), bounds.centerX(), bounds.centerY(), scale * 1.7f, colorAlpha(0xFF3EC5FF, 0.75f * shine), ALIGN_CENTER); + if (img) { + float scale = bounds.w / img->w; + dc.Draw()->DrawImage(ImageID("I_DROP_SHADOW"), bounds.centerX(), bounds.centerY(), scale * 1.7f, colorAlpha(0xFF3EC5FF, 0.75f * shine), ALIGN_CENTER); + } dc.Flush(); } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 250cf1425d..f23151fdce 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -87,6 +87,7 @@ #include "Common/VR/PPSSPPVR.h" #include "Common/Thread/ThreadManager.h" #include "Common/Audio/AudioBackend.h" +#include "Common/Render/ManagedTexture.h" #include "Core/ControlMapper.h" #include "Core/Config.h" @@ -820,6 +821,40 @@ static void NativeMixWrapper(float *dest, int framesToWrite, int sampleRateHz, v } } +static AtlasData AtlasProvider(Draw::DrawContext *draw, AtlasChoice atlas) { + switch (atlas) { + case AtlasChoice::General: + return { + GetUIAtlas(), + CreateTextureFromFile(draw, "ui_atlas.zim", ImageFileType::ZIM, false) + }; + case AtlasChoice::Font: + { + Draw::Texture *fontTexture = nullptr; + // NOTE: This ugly check must be the same as the one in UpdateTheme. This will be fixed. +#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) + // Don't bother with loading font_atlas.zim +#else + fontTexture = CreateTextureFromFile(draw_, "font_atlas.zim", ImageFileType::ZIM, false); +#endif + if (!fontTexture) { + // Load the smaller ascii font only, like on Android. For debug ui etc. + // NOTE: We better be sure here that the correct metadata is loaded.. + fontTexture = CreateTextureFromFile(draw, "asciifont_atlas.zim", ImageFileType::ZIM, false); + if (!fontTexture) { + WARN_LOG(Log::System, "Failed to load font_atlas.zim or asciifont_atlas.zim"); + } + } + return { + GetFontAtlas(), + fontTexture, + }; + } + default: + return {}; + }; +} + bool NativeInitGraphics(GraphicsContext *graphicsContext) { INFO_LOG(Log::System, "NativeInitGraphics"); @@ -843,6 +878,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { uiContext = new UIContext(); uiContext->SetTheme(GetTheme()); + uiContext->SetAtlasProvider(&AtlasProvider); UpdateTheme(); ui_draw2d.Init(g_draw, texColorPipeline); diff --git a/UI/Theme.cpp b/UI/Theme.cpp index e42939a0d0..446bc777c8 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -254,10 +254,10 @@ void UpdateTheme() { // Load any missing atlas metadata (the images are loaded from UIContext). LoadAtlasMetadata(ui_atlas, "ui_atlas.meta", true); -#if !(PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID)) - LoadAtlasMetadata(font_atlas, "font_atlas.meta", ui_atlas.num_fonts == 0); -#else +#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) LoadAtlasMetadata(font_atlas, "asciifont_atlas.meta", ui_atlas.num_fonts == 0); +#else + LoadAtlasMetadata(font_atlas, "font_atlas.meta", ui_atlas.num_fonts == 0); #endif } From 2bab844852641648870d7380a271859bd8dc77c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 15 Sep 2025 14:18:10 -0600 Subject: [PATCH 3/3] Do the loading of the atlas texture and metadata together. --- UI/NativeApp.cpp | 36 -------------------------------- UI/Theme.cpp | 53 ++++++++++++++++++++++++++++++++++++------------ UI/Theme.h | 2 ++ 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index f23151fdce..e2179fb55e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -87,8 +87,6 @@ #include "Common/VR/PPSSPPVR.h" #include "Common/Thread/ThreadManager.h" #include "Common/Audio/AudioBackend.h" -#include "Common/Render/ManagedTexture.h" - #include "Core/ControlMapper.h" #include "Core/Config.h" #include "Core/ConfigValues.h" @@ -821,40 +819,6 @@ static void NativeMixWrapper(float *dest, int framesToWrite, int sampleRateHz, v } } -static AtlasData AtlasProvider(Draw::DrawContext *draw, AtlasChoice atlas) { - switch (atlas) { - case AtlasChoice::General: - return { - GetUIAtlas(), - CreateTextureFromFile(draw, "ui_atlas.zim", ImageFileType::ZIM, false) - }; - case AtlasChoice::Font: - { - Draw::Texture *fontTexture = nullptr; - // NOTE: This ugly check must be the same as the one in UpdateTheme. This will be fixed. -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - // Don't bother with loading font_atlas.zim -#else - fontTexture = CreateTextureFromFile(draw_, "font_atlas.zim", ImageFileType::ZIM, false); -#endif - if (!fontTexture) { - // Load the smaller ascii font only, like on Android. For debug ui etc. - // NOTE: We better be sure here that the correct metadata is loaded.. - fontTexture = CreateTextureFromFile(draw, "asciifont_atlas.zim", ImageFileType::ZIM, false); - if (!fontTexture) { - WARN_LOG(Log::System, "Failed to load font_atlas.zim or asciifont_atlas.zim"); - } - } - return { - GetFontAtlas(), - fontTexture, - }; - } - default: - return {}; - }; -} - bool NativeInitGraphics(GraphicsContext *graphicsContext) { INFO_LOG(Log::System, "NativeInitGraphics"); diff --git a/UI/Theme.cpp b/UI/Theme.cpp index 446bc777c8..98e476cd2f 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -26,6 +26,7 @@ #include "Common/Data/Format/IniFile.h" #include "Common/File/DirListing.h" #include "Common/Log/LogManager.h" +#include "Common/Render/ManagedTexture.h" #include "Core/Config.h" @@ -171,15 +172,12 @@ static UI::Style MakeStyle(uint32_t fg, uint32_t bg) { return s; } -static void LoadAtlasMetadata(Atlas &metadata, const char *filename, bool required) { +static void LoadAtlasMetadata(Atlas &metadata, const char *filename) { size_t atlas_data_size = 0; const uint8_t *atlas_data = g_VFS.ReadFile(filename, &atlas_data_size); bool load_success = atlas_data != nullptr && metadata.Load(atlas_data, atlas_data_size); if (!load_success) { - if (required) - ERROR_LOG(Log::G3D, "Failed to load %s - graphics will be broken", filename); - else - WARN_LOG(Log::G3D, "Failed to load %s", filename); + ERROR_LOG(Log::G3D, "Failed to load %s - graphics may be broken", filename); // Stumble along with broken visuals instead of dying... } delete[] atlas_data; @@ -251,14 +249,6 @@ void UpdateTheme() { ui_theme.popupSliderColor = themeInfo.uPopupSliderColor; ui_theme.popupSliderFocusedColor = themeInfo.uPopupSliderFocusedColor; - - // Load any missing atlas metadata (the images are loaded from UIContext). - LoadAtlasMetadata(ui_atlas, "ui_atlas.meta", true); -#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - LoadAtlasMetadata(font_atlas, "asciifont_atlas.meta", ui_atlas.num_fonts == 0); -#else - LoadAtlasMetadata(font_atlas, "font_atlas.meta", ui_atlas.num_fonts == 0); -#endif } UI::Theme *GetTheme() { @@ -287,3 +277,40 @@ std::vector GetThemeInfoNames() { return names; } + +AtlasData AtlasProvider(Draw::DrawContext *draw, AtlasChoice atlas) { + switch (atlas) { + case AtlasChoice::General: + { + // Load any missing atlas metadata (the images are loaded from UIContext). + LoadAtlasMetadata(ui_atlas, "ui_atlas.meta"); + return { + &ui_atlas, + CreateTextureFromFile(draw, "ui_atlas.zim", ImageFileType::ZIM, false) + }; + } + case AtlasChoice::Font: + { + Draw::Texture *fontTexture = nullptr; +#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) + // Load the smaller ascii font only, like on Android. For debug ui etc. + // NOTE: We better be sure here that the correct metadata is loaded.. + LoadAtlasMetadata(font_atlas, "asciifont_atlas.meta"); + fontTexture = CreateTextureFromFile(draw, "asciifont_atlas.zim", ImageFileType::ZIM, false); + if (!fontTexture) { + WARN_LOG(Log::System, "Failed to load font_atlas.zim or asciifont_atlas.zim"); + } +#else + // Load the full font texture. + LoadAtlasMetadata(font_atlas, "font_atlas.meta"); + fontTexture = CreateTextureFromFile(draw, "font_atlas.zim", ImageFileType::ZIM, false); +#endif + return { + &font_atlas, + fontTexture, + }; + } + default: + return {}; + }; +} diff --git a/UI/Theme.h b/UI/Theme.h index deeb59df1f..ed0dc68a55 100644 --- a/UI/Theme.h +++ b/UI/Theme.h @@ -30,3 +30,5 @@ void UpdateTheme(); Atlas *GetFontAtlas(); Atlas *GetUIAtlas(); UI::Theme *GetTheme(); + +AtlasData AtlasProvider(Draw::DrawContext *draw, AtlasChoice atlas);