Skip to content

Commit

Permalink
Merge branch 'master' into string_view
Browse files Browse the repository at this point in the history
  • Loading branch information
jhasse committed Oct 24, 2024
2 parents f314e63 + 272ec0d commit 50ba5b1
Show file tree
Hide file tree
Showing 16 changed files with 174 additions and 74 deletions.
13 changes: 7 additions & 6 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@ steamos:
image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk
stage: build
script:
- cd /usr/local/include
- curl --silent -O -L https://boostorg.jfrog.io/artifactory/main/release/1.80.0/source/boost_1_80_0.tar.bz2
- tar -xf *.tar.bz2 --strip-components=1 boost_1_80_0/boost
- cd -
- cmake -Bbuild-steamos -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=0
- apt-get install -y libboost-dev libc++abi-16-dev libc++-16-dev clang-16
- export LDFLAGS=-static-libstdc++
- export CXXFLAGS=-stdlib=libc++
- export CC=clang-16
- export CXX=clang++-16
- cmake -Bbuild-steamos -GNinja -DCMAKE_BUILD_TYPE=Debug
- cmake --build build-steamos
- cmake -Bbuild-steamos-release -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=0 -DJNGL_VIDEO=0 -DJNGL_BUILD_WEBP_FROM_SOURCE=1 -DBUILD_SHARED_LIBS=0
- cmake -Bbuild-steamos-release -GNinja -DCMAKE_BUILD_TYPE=Release -DJNGL_VIDEO=0 -DJNGL_BUILD_WEBP_FROM_SOURCE=1 -DBUILD_SHARED_LIBS=0
- cmake --build build-steamos-release

web:
Expand Down
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ if(ANDROID OR MSVC OR IOS)
endif()

get_directory_property(hasParent PARENT_DIRECTORY)
if(NOT hasParent)
option(JNGL_SANITIZE_ADDRESS "Enable AddressSanitizer" OFF)
if(JNGL_SANITIZE_ADDRESS)
string(APPEND CMAKE_CXX_FLAGS " -fsanitize=address")
string(APPEND CMAKE_LINKER_FLAGS " -fsanitize=address")
endif()
endif()
if(ANDROID OR MSVC OR IOS)
CPMAddPackage(NAME freetype
URL https://sourceforge.net/projects/freetype/files/freetype2/2.11.1/freetype-2.11.1.tar.xz/download
Expand Down Expand Up @@ -383,6 +390,8 @@ else()
add_executable(audioplayer examples/audioplayer.cpp)
target_link_libraries(audioplayer PRIVATE jngl)
add_custom_command(TARGET audioplayer COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/data/test.ogg "$<TARGET_FILE_DIR:audioplayer>")
# add_executable(benchmark-shapes src/benchmarks/benchmark-shapes.cpp)
# target_link_libraries(benchmark-shapes jngl)
endif()
endif()
target_link_libraries(jngl-test jngl)
Expand Down
37 changes: 37 additions & 0 deletions src/TextureCache.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt
#include "TextureCache.hpp"

#include <cassert>

namespace jngl {

std::shared_ptr<Texture> TextureCache::get(std::string_view filename) {
#if __cpp_lib_generic_unordered_lookup
auto it = textures.find(filename);
#else
auto it = textures.find(std::string(filename));
#endif
if (it == textures.end()) {
return nullptr;
}
return it->second;
}

void TextureCache::insert(std::string_view filename, std::shared_ptr<Texture> texture) {
auto result [[maybe_unused]] = textures.emplace(filename, std::move(texture));
assert(result.second);
}

void TextureCache::remove(std::string_view filename) {
#if __cpp_lib_generic_unordered_lookup
auto it = textures.find(filename);
#else
auto it = textures.find(std::string(filename));
#endif
if (it != textures.end()) {
textures.erase(it);
}
}

} // namespace jngl
37 changes: 37 additions & 0 deletions src/TextureCache.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt
#pragma once

#include "jngl/Singleton.hpp"

#include <memory>

namespace jngl {

class Texture;

class TextureCache : public Singleton<TextureCache> {
public:
std::shared_ptr<Texture> get(std::string_view filename);
void insert(std::string_view filename, std::shared_ptr<Texture>);
void remove(std::string_view filename);

private:
// https://www.cppstories.com/2021/heterogeneous-access-cpp20/
struct string_hash {
using is_transparent = void;
[[nodiscard]] size_t operator()(const char* txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(std::string_view txt) const {
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] size_t operator()(const std::string& txt) const {
return std::hash<std::string>{}(txt);
}
};
std::unordered_map<std::string, std::shared_ptr<Texture>, string_hash, std::equal_to<>>
textures;
};

} // namespace jngl
10 changes: 8 additions & 2 deletions src/audio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
#include "audio/engine.hpp"
#include "jngl/Singleton.hpp"

#include <future>
#include <memory>

namespace jngl {

class Channel;
class Mixer;
class Sound;
class SoundFile;

namespace audio {
struct pitch_control;
Expand Down Expand Up @@ -40,16 +42,20 @@ class Audio : public jngl::Singleton<Audio> {
Channel& getMainChannel();
void registerChannel(std::shared_ptr<Stream>);
void unregisterChannel(const Stream&);
void step();
void step();
std::shared_ptr<SoundFile> getSoundFile(const std::string& filename, std::launch policy);

private:
std::vector<std::shared_ptr<Sound>> sounds_;
std::shared_ptr<Mixer> mixer;
std::unique_ptr<Channel> mainChannel;
std::shared_ptr<audio::pitch_control> pitchControl;
std::shared_ptr<audio::volume_control> volumeControl;
audio::engine engine;
uint8_t pauseDeviceCount = 0; //< if >0 audio device is paused
std::unordered_map<std::string, std::shared_ptr<SoundFile>> soundFiles;
// engine has to be declared after soundFiles so that the mixer thread gets joined and closed
// before any SoundFile is destroyed:
audio::engine engine;
};

} // namespace jngl
9 changes: 3 additions & 6 deletions src/jngl/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,18 @@ Channel::~Channel() {
}
}

// defined in SoundFile.cpp
std::shared_ptr<SoundFile> getSoundFile(const std::string& filename, std::launch policy);

void Channel::play(const std::string& filename) {
getSoundFile(filename, std::launch::deferred)->play(*this);
Audio::handle().getSoundFile(filename, std::launch::deferred)->play(*this);
}

std::shared_ptr<SoundFile> Channel::loop(const std::string& filename) {
auto tmp = getSoundFile(filename, std::launch::deferred);
auto tmp = Audio::handle().getSoundFile(filename, std::launch::deferred);
tmp->loop(*this);
return tmp;
}

void Channel::stop(const std::string& filename) {
getSoundFile(filename, std::launch::async)->stop(*this);
Audio::handle().getSoundFile(filename, std::launch::async)->stop(*this);
}

Finally Channel::pause() {
Expand Down
6 changes: 3 additions & 3 deletions src/jngl/FrameBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ FrameBuffer::Context FrameBuffer::use() const {
};
pushMatrix();
reset();
opengl::scale(static_cast<float>(pWindow->getCanvasWidth()) / static_cast<float>(impl->width) *
opengl::scale(static_cast<float>(pWindow->getWidth()) / static_cast<float>(impl->width) *
pWindow->getResizedWindowScalingX(),
static_cast<float>(pWindow->getCanvasHeight()) /
static_cast<float>(impl->height) * pWindow->getResizedWindowScalingY());
static_cast<float>(pWindow->getHeight()) / static_cast<float>(impl->height) *
pWindow->getResizedWindowScalingY());
#if defined(GL_VIEWPORT_BIT) && !defined(__APPLE__)
glPushAttrib(GL_VIEWPORT_BIT);
#else
Expand Down
11 changes: 7 additions & 4 deletions src/jngl/Singleton.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ template <class T> class Singleton {
static T& handle() {
if (!instance) {
instance = new T;
atExit([]() {
delete instance;
instance = nullptr;
});
atExit(&Singleton::destroy);
}
return *instance;
}
Expand All @@ -45,6 +42,12 @@ template <class T> class Singleton {
return instance;
}

/// Deletes the Singleton
static void destroy() noexcept {
delete instance;
instance = nullptr;
}

protected:
Singleton() = default;

Expand Down
24 changes: 10 additions & 14 deletions src/jngl/SoundFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@

namespace jngl {

// TODO: Move to Audio
std::unordered_map<std::string, std::shared_ptr<SoundFile>> sounds;

Audio::Audio()
: mixer(std::make_shared<Mixer>()), pitchControl(audio::pitch(mixer)),
volumeControl(volume(pitchControl)), engine(volumeControl) {
Expand Down Expand Up @@ -251,35 +248,34 @@ float SoundFile::progress() const {
return sound_ ? sound_->progress() : 0;
}

std::shared_ptr<SoundFile> getSoundFile(const std::string& filename, std::launch policy) {
Audio::handle();
auto i = sounds.find(filename);
if (i == sounds.end()) { // sound hasn't been loaded yet?
sounds[filename] = std::make_shared<SoundFile>(pathPrefix + filename, policy);
return sounds[filename];
std::shared_ptr<SoundFile> Audio::getSoundFile(const std::string& filename, std::launch policy) {
auto i = soundFiles.find(filename);
if (i == soundFiles.end()) { // sound hasn't been loaded yet?
soundFiles[filename] = std::make_shared<SoundFile>(pathPrefix + filename, policy);
return soundFiles[filename];
}
return i->second;
}

void play(const std::string& filename) {
getSoundFile(filename, std::launch::deferred)->play();
Audio::handle().getSoundFile(filename, std::launch::deferred)->play();
}

void stop(const std::string& filename) {
getSoundFile(filename, std::launch::async)->stop();
Audio::handle().getSoundFile(filename, std::launch::async)->stop();
}

Finally loadSound(const std::string& filename) {
auto soundFile = getSoundFile(filename, std::launch::async);
auto soundFile = Audio::handle().getSoundFile(filename, std::launch::async);
return Finally([soundFile = std::move(soundFile)]() { soundFile->load(); });
}

bool isPlaying(const std::string& filename) {
return getSoundFile(filename, std::launch::async)->isPlaying();
return Audio::handle().getSoundFile(filename, std::launch::async)->isPlaying();
}

std::shared_ptr<SoundFile> loop(const std::string& filename) {
auto tmp = getSoundFile(filename, std::launch::deferred);
auto tmp = Audio::handle().getSoundFile(filename, std::launch::deferred);
tmp->loop();
return tmp;
}
Expand Down
22 changes: 7 additions & 15 deletions src/jngl/sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "sprite.hpp"

#include "../TextureCache.hpp"
#include "../helper.hpp"
#include "../log.hpp"
#include "../main.hpp"
Expand Down Expand Up @@ -38,31 +39,21 @@

namespace jngl {

std::shared_ptr<Texture> getTexture(std::string_view filename) {
auto it = textures.find(filename);
if (it == textures.end()) {
return nullptr;
}
return it->second;
}

Sprite::Sprite(const ImageData& imageData, double scale, std::optional<std::string_view> filename) {
if (!pWindow) {
throw std::runtime_error("Window hasn't been created yet.");
}
width = scale * imageData.getWidth();
height = scale * imageData.getHeight();
auto it = filename ? textures.find(std::string(*filename)) : textures.end();
if (it == textures.end()) {
texture = filename ? TextureCache::handle().get(*filename) : nullptr;
if (!texture) {
texture = std::make_shared<Texture>(
static_cast<int>(std::lround(width)), static_cast<int>(std::lround(height)),
imageData.getWidth(), imageData.getHeight(), nullptr, GL_RGBA, imageData.pixels());
setCenter(0, 0);
if (filename) {
textures[std::string(*filename)] = texture;
TextureCache::handle().insert(*filename, texture);
}
} else {
texture = it->second;
}
}

Expand All @@ -76,7 +67,8 @@ Sprite::Sprite(const uint8_t* const bytes, const size_t width, const size_t heig
setCenter(0, 0);
}

Sprite::Sprite(std::string_view filename, LoadType loadType) : texture(getTexture(filename)) {
Sprite::Sprite(std::string_view filename, LoadType loadType)
: texture(TextureCache::handle().get(filename)) {
if (texture) {
width = texture->getPreciseWidth();
height = texture->getPreciseHeight();
Expand Down Expand Up @@ -468,7 +460,7 @@ void Sprite::loadTexture(const int scaledWidth, const int scaledHeight, std::str
}
texture = std::make_shared<Texture>(width, height, scaledWidth, scaledHeight, rowPointers,
format, data);
textures[filename] = texture;
TextureCache::handle().insert(filename, texture);
}

Finally disableBlending() {
Expand Down
5 changes: 2 additions & 3 deletions src/jngl/work.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012-2023 Jan Niklas Hasse <jhasse@bixense.com>
// Copyright 2012-2024 Jan Niklas Hasse <jhasse@bixense.com>
// For conditions of distribution and use, see copyright notice in LICENSE.txt

#include "work.hpp"
Expand All @@ -8,11 +8,10 @@
namespace jngl {

void Work::onBackEvent() {
onQuitEvent();
jngl::quit();
}

void Work::onQuitEvent() {
jngl::quit();
}

void Work::onControllerBack() {
Expand Down
Loading

0 comments on commit 50ba5b1

Please sign in to comment.