fix nvjpg icon loading if w*bpp != pitch. add build option to enable/disable nvjpg (for testing).
This commit is contained in:
@@ -208,6 +208,8 @@ FetchContent_Declare(nvjpg
|
||||
)
|
||||
|
||||
set(USE_NEW_ZSTD ON)
|
||||
# has issues with some homebrew and game icons (oxenfree, overwatch2).
|
||||
set(USE_NVJPG ON)
|
||||
|
||||
set(ZSTD_BUILD_STATIC ON)
|
||||
set(ZSTD_BUILD_SHARED OFF)
|
||||
@@ -310,13 +312,15 @@ add_library(libnxtc
|
||||
)
|
||||
target_include_directories(libnxtc PUBLIC ${libnxtc_SOURCE_DIR}/include)
|
||||
|
||||
add_library(nvjpg
|
||||
${nvjpg_SOURCE_DIR}/lib/decoder.cpp
|
||||
${nvjpg_SOURCE_DIR}/lib/image.cpp
|
||||
${nvjpg_SOURCE_DIR}/lib/surface.cpp
|
||||
)
|
||||
target_include_directories(nvjpg PUBLIC ${nvjpg_SOURCE_DIR}/include)
|
||||
set_target_properties(nvjpg PROPERTIES CXX_STANDARD 26)
|
||||
if (USE_NVJPG)
|
||||
add_library(nvjpg
|
||||
${nvjpg_SOURCE_DIR}/lib/decoder.cpp
|
||||
${nvjpg_SOURCE_DIR}/lib/image.cpp
|
||||
${nvjpg_SOURCE_DIR}/lib/surface.cpp
|
||||
)
|
||||
target_include_directories(nvjpg PUBLIC ${nvjpg_SOURCE_DIR}/include)
|
||||
set_target_properties(nvjpg PROPERTIES CXX_STANDARD 26)
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_library(minizip_lib minizip REQUIRED)
|
||||
@@ -348,7 +352,6 @@ target_link_libraries(sphaira PRIVATE
|
||||
yyjson
|
||||
# libusbhsfs
|
||||
libnxtc
|
||||
nvjpg
|
||||
|
||||
${minizip_lib}
|
||||
ZLIB::ZLIB
|
||||
@@ -365,6 +368,11 @@ else()
|
||||
target_include_directories(sphaira PRIVATE ${zstd_inc})
|
||||
endif()
|
||||
|
||||
if (USE_NVJPG)
|
||||
target_link_libraries(sphaira PRIVATE nvjpg)
|
||||
target_compile_definitions(sphaira PRIVATE USE_NVJPG)
|
||||
endif()
|
||||
|
||||
target_include_directories(sphaira PRIVATE
|
||||
include
|
||||
${minizip_inc}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include "fs.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
#ifdef USE_NVJPG
|
||||
#include <nvjpg.hpp>
|
||||
#endif
|
||||
#include <switch.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -273,7 +275,9 @@ public:
|
||||
|
||||
PLSR_PlayerSoundId m_sound_ids[SoundEffect_MAX]{};
|
||||
|
||||
#ifdef USE_NVJPG
|
||||
nj::Decoder m_decoder;
|
||||
#endif
|
||||
|
||||
private: // from nanovg decko3d example by adubbz
|
||||
static constexpr unsigned NumFramebuffers = 2;
|
||||
|
||||
@@ -1400,9 +1400,11 @@ App::App(const char* argv0) {
|
||||
|
||||
curl::Init();
|
||||
|
||||
#ifdef USE_NVJPG
|
||||
// this has to be init before deko3d.
|
||||
nj::initialize();
|
||||
m_decoder.initialize();
|
||||
#endif
|
||||
|
||||
// get current size of the framebuffer
|
||||
const auto fb = GetFrameBufferSize();
|
||||
@@ -1883,8 +1885,10 @@ App::~App() {
|
||||
nvgDeleteDk(this->vg);
|
||||
this->renderer.reset();
|
||||
|
||||
#ifdef USE_NVJPG
|
||||
m_decoder.finalize();
|
||||
nj::finalize();
|
||||
#endif
|
||||
|
||||
// backup hbmenu if it is not sphaira
|
||||
if (App::GetReplaceHbmenuEnable() && !IsHbmenu()) {
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
|
||||
#include "app.hpp"
|
||||
#include "log.hpp"
|
||||
#ifdef USE_NVJPG
|
||||
#include <nvjpg.hpp>
|
||||
#endif
|
||||
#include <cstring>
|
||||
|
||||
namespace sphaira {
|
||||
@@ -45,6 +47,7 @@ auto ImageLoadInternal(stbi_uc* image_data, int x, int y) -> ImageResult {
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef USE_NVJPG
|
||||
auto ImageLoadInternal(nj::Image&& image) -> ImageResult {
|
||||
if (!image.is_valid() || image.parse()) {
|
||||
log_write("[NVJPG] failed to parse image\n");
|
||||
@@ -68,17 +71,29 @@ auto ImageLoadInternal(nj::Image&& image) -> ImageResult {
|
||||
}
|
||||
|
||||
ImageResult result{};
|
||||
result.w = image.width;
|
||||
result.h = image.height;
|
||||
result.data.resize(surf.size());
|
||||
std::memcpy(result.data.data(), surf.data(), result.data.size());
|
||||
result.w = surf.width;
|
||||
result.h = surf.height;
|
||||
result.data.resize(surf.width * surf.height * surf.get_bpp());
|
||||
// std::printf("[NVJPG] w: %zu h: %zu bpp: %u pitch: %zu size: %zu size2: %u\n", surf.width, surf.height, surf.get_bpp(), surf.pitch, surf.size(), 256*256*4);
|
||||
|
||||
if (surf.width * surf.get_bpp() == surf.pitch) [[likely]] {
|
||||
std::memcpy(result.data.data(), surf.data(), result.data.size());
|
||||
} else {
|
||||
for (size_t i = 0; i < surf.height; i++) {
|
||||
const auto src_pitch = surf.pitch;
|
||||
const auto dst_pitch = surf.width * surf.get_bpp();
|
||||
std::memcpy(result.data.data() + i * dst_pitch, surf.data() + i * src_pitch, dst_pitch);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
auto ImageLoadFromMemory(std::span<const u8> data, u32 flags) -> ImageResult {
|
||||
#ifdef USE_NVJPG
|
||||
if (flags & ImageFlag_JPEG) {
|
||||
auto shared_vec = std::make_shared<std::vector<u8>>(data.size());
|
||||
std::memcpy(shared_vec->data(), data.data(), shared_vec->size());
|
||||
@@ -86,19 +101,26 @@ auto ImageLoadFromMemory(std::span<const u8> data, u32 flags) -> ImageResult {
|
||||
auto result = ImageLoadInternal(nj::Image{shared_vec});
|
||||
// if it failed, try again but without using oss-jpg.
|
||||
return result.data.empty() ? ImageLoadFromMemory(data, 0) : result;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int x, y, channels;
|
||||
return ImageLoadInternal(stbi_load_from_memory(data.data(), data.size(), &x, &y, &channels, BPP), x, y);
|
||||
}
|
||||
}
|
||||
|
||||
auto ImageLoadFromFile(const fs::FsPath& file, u32 flags) -> ImageResult {
|
||||
#ifdef USE_NVJPG
|
||||
if (flags & ImageFlag_JPEG) {
|
||||
// don't make const as it prevents RTO.
|
||||
auto result = ImageLoadInternal(nj::Image{file});
|
||||
// if it failed, try again but without using oss-jpg.
|
||||
return result.data.empty() ? ImageLoadFromFile(file, 0) : result;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
int x, y, channels;
|
||||
return ImageLoadInternal(stbi_load(file, &x, &y, &channels, BPP), x, y);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user