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