├── demo ├── android │ ├── settings.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── app │ │ ├── src │ │ │ └── main │ │ │ │ ├── res │ │ │ │ └── values │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── themes.xml │ │ │ │ ├── java │ │ │ │ └── graphics │ │ │ │ │ └── pathfinder │ │ │ │ │ └── demo │ │ │ │ │ └── MainActivity.java │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── cpp │ │ │ │ ├── native_engine.h │ │ │ │ ├── GameActivitySources.cpp │ │ │ │ ├── AndroidMain.cpp │ │ │ │ └── CMakeLists.txt │ │ └── build.gradle │ ├── gradle.properties │ ├── build.gradle │ └── .gitignore ├── web │ ├── serve.sh │ ├── serve.ps1 │ ├── CMakeLists.txt │ └── main.cpp ├── native │ └── CMakeLists.txt └── common │ ├── CMakeLists.txt │ ├── app.h │ └── blit.h ├── assets └── sea.png ├── pathfinder ├── gpu │ ├── README.md │ ├── fence.h │ ├── compute_pipeline.h │ ├── shader_module.h │ ├── gl │ │ ├── fence.cpp │ │ ├── fence.h │ │ ├── render_pass.h │ │ ├── command_encoder.h │ │ ├── compute_pipeline.h │ │ ├── buffer.h │ │ ├── shader_module.h │ │ ├── texture.h │ │ ├── framebuffer.h │ │ ├── window.h │ │ ├── window_builder.h │ │ ├── queue.h │ │ ├── window.cpp │ │ ├── render_pipeline.h │ │ ├── framebuffer.cpp │ │ ├── texture.cpp │ │ ├── shader_module.cpp │ │ ├── program.h │ │ └── debug_marker.h │ ├── vk │ │ ├── fence.cpp │ │ ├── fence.h │ │ ├── shader_module.h │ │ ├── render_pass.h │ │ ├── descriptor_set.h │ │ ├── command_encoder.h │ │ ├── queue.h │ │ ├── framebuffer.h │ │ ├── window.h │ │ ├── buffer.h │ │ ├── compute_pipeline.h │ │ ├── render_pipeline.h │ │ ├── queue.cpp │ │ ├── window.cpp │ │ ├── framebuffer.cpp │ │ └── buffer.cpp │ ├── render_pass.h │ ├── queue.h │ ├── render_api.h │ ├── render_pipeline.h │ ├── framebuffer.h │ ├── swap_chain.h │ ├── buffer.h │ ├── window.h │ ├── texture.h │ └── window_builder.h ├── shaders │ ├── area_lut.png │ ├── blit.vert │ ├── blit.frag │ ├── d3d9 │ │ ├── tile_clip_copy.frag │ │ ├── tile_clip_combine.frag │ │ ├── tile_clip_copy.vert │ │ ├── fill.frag │ │ └── tile_clip_combine.vert │ ├── generated │ │ ├── blit_vert.h │ │ ├── blit_frag_spv.h │ │ ├── tile_clip_copy_frag_spv.h │ │ ├── blit_frag.h │ │ ├── blit_vert_spv.h │ │ └── tile_clip_combine_frag_spv.h │ ├── convert_files_to_header.py │ ├── compile_and_convert.ps1 │ └── d3d11 │ │ ├── bound.comp │ │ └── sort.comp ├── core │ ├── d3d9 │ │ ├── data │ │ │ ├── alpha_tile_id.cpp │ │ │ ├── alpha_tile_id.h │ │ │ ├── gpu_data.h │ │ │ └── draw_tile_batch.h │ │ ├── tiler.h │ │ └── object_builder.h │ ├── svg.h │ ├── data │ │ ├── path.cpp │ │ ├── built_path.cpp │ │ ├── path.h │ │ └── built_path.h │ ├── dash.h │ ├── scene_builder.cpp │ ├── scene_builder.h │ ├── paint │ │ ├── pattern.cpp │ │ └── paint.cpp │ ├── path2d.h │ ├── stroke.h │ └── d3d11 │ │ └── scene_builder.h ├── CMakeLists.txt ├── prelude.h └── common │ ├── math │ ├── unit_vector.cpp │ ├── unit_vector.h │ ├── vec3.h │ ├── transform2.cpp │ ├── mat3.h │ ├── mat4.h │ ├── mat2.h │ └── basic.h │ ├── timestamp.h │ ├── io.h │ ├── timestamp.cpp │ ├── global_macros.h │ ├── color.cpp │ └── i32x4.h ├── third_party └── glfw │ ├── CMake │ ├── glfw3Config.cmake.in │ ├── glfw3.pc.in │ ├── modules │ │ ├── FindOSMesa.cmake │ │ └── FindEpollShim.cmake │ ├── i686-w64-mingw32.cmake │ ├── i686-w64-mingw32-clang.cmake │ ├── x86_64-w64-mingw32.cmake │ ├── x86_64-w64-mingw32-clang.cmake │ ├── cmake_uninstall.cmake.in │ ├── Info.plist.in │ └── GenerateMappings.cmake │ ├── .mailmap │ ├── src │ ├── glfw.rc.in │ ├── xkb_unicode.h │ ├── cocoa_time.h │ ├── null_joystick.h │ ├── posix_poll.h │ ├── win32_time.h │ ├── posix_time.h │ ├── posix_thread.h │ ├── win32_thread.h │ ├── cocoa_joystick.h │ ├── win32_joystick.h │ ├── null_joystick.c │ ├── win32_module.c │ ├── posix_module.c │ ├── cocoa_time.c │ ├── win32_time.c │ ├── linux_joystick.h │ └── posix_time.c │ ├── LICENSE.md │ └── deps │ └── getopt.h ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md └── .github └── workflows └── cmake.yml /demo/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /demo/web/serve.sh: -------------------------------------------------------------------------------- 1 | python3 -m http.server 2 | -------------------------------------------------------------------------------- /assets/sea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/floppyhammer/pathfinder-cpp/HEAD/assets/sea.png -------------------------------------------------------------------------------- /demo/web/serve.ps1: -------------------------------------------------------------------------------- 1 | python -m http.server 2 | 3 | $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") 4 | -------------------------------------------------------------------------------- /pathfinder/gpu/README.md: -------------------------------------------------------------------------------- 1 | # Pathfinder GPU 2 | 3 | This is a minimal GPU abstraction layer tailored for Pathfinder. 4 | -------------------------------------------------------------------------------- /pathfinder/shaders/area_lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/floppyhammer/pathfinder-cpp/HEAD/pathfinder/shaders/area_lut.png -------------------------------------------------------------------------------- /demo/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/floppyhammer/pathfinder-cpp/HEAD/demo/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /third_party/glfw/CMake/glfw3Config.cmake.in: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | find_dependency(Threads) 3 | include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake") 4 | -------------------------------------------------------------------------------- /demo/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Pathfinder Demo 4 | 5 | -------------------------------------------------------------------------------- /demo/native/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Build executable. 2 | add_executable(pathfinder_demo_native main.cpp) 3 | 4 | # Link libraries. 5 | target_link_libraries(pathfinder_demo_native pathfinder_demo_common pathfinder) 6 | -------------------------------------------------------------------------------- /demo/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | android.useAndroidX=true 3 | android.prefabVersion=2.0.0 4 | android.nonTransitiveRClass=false 5 | android.defaults.buildfeatures.buildconfig=true 6 | android.nonFinalResIds=false 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | bin/ 3 | 4 | # Build files 5 | cmake-build-debug/ 6 | cmake-build-release/ 7 | cmake-build-relwithdebinfo/ 8 | 9 | # Jetbrains IDEs 10 | .idea/ 11 | 12 | # Android demo assets 13 | demo/android/app/src/main/assets/ 14 | -------------------------------------------------------------------------------- /demo/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /demo/web/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Include Pathfinder headers. 2 | include_directories(../../) 3 | 4 | # Build executable. 5 | add_executable(pathfinder_demo_web main.cpp) 6 | 7 | # Link libraries. 8 | target_link_libraries(pathfinder_demo_web pathfinder_demo_common pathfinder) 9 | -------------------------------------------------------------------------------- /pathfinder/shaders/blit.vert: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | layout(location = 0) in vec2 aPos; 4 | layout(location = 1) in vec2 aUV; 5 | 6 | #ifdef VULKAN 7 | layout(location = 0) out vec2 vUV; 8 | #else 9 | out vec2 vUV; 10 | #endif 11 | 12 | void main() { 13 | vUV = aUV; 14 | 15 | gl_Position = vec4(aPos, 0.0, 1.0); 16 | } 17 | -------------------------------------------------------------------------------- /demo/android/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /pathfinder/gpu/fence.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FENCE_H 2 | #define PATHFINDER_GPU_FENCE_H 3 | 4 | #include 5 | 6 | namespace Pathfinder { 7 | 8 | class SwapChain; 9 | 10 | class Fence { 11 | public: 12 | Fence() = default; 13 | 14 | std::string label; 15 | }; 16 | 17 | } // namespace Pathfinder 18 | 19 | #endif // PATHFINDER_GPU_FENCE_H 20 | -------------------------------------------------------------------------------- /pathfinder/gpu/compute_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_COMPUTE_PIPELINE_H 2 | #define PATHFINDER_GPU_COMPUTE_PIPELINE_H 3 | 4 | #include 5 | 6 | namespace Pathfinder { 7 | 8 | class ComputePipeline { 9 | public: 10 | virtual ~ComputePipeline() = default; 11 | 12 | protected: 13 | std::string label_; 14 | }; 15 | 16 | } // namespace Pathfinder 17 | 18 | #endif // PATHFINDER_GPU_COMPUTE_PIPELINE_H 19 | -------------------------------------------------------------------------------- /third_party/glfw/.mailmap: -------------------------------------------------------------------------------- 1 | Camilla Löwy 2 | Camilla Löwy 3 | Camilla Löwy 4 | 5 | Emmanuel Gil Peyrot 6 | 7 | Marcus Geelnard 8 | Marcus Geelnard 9 | Marcus Geelnard 10 | 11 | -------------------------------------------------------------------------------- /pathfinder/gpu/shader_module.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_SHADER_MODULE_H 2 | #define PATHFINDER_GPU_SHADER_MODULE_H 3 | 4 | #include 5 | 6 | namespace Pathfinder { 7 | 8 | class ShaderModule { 9 | public: 10 | virtual ~ShaderModule() = default; 11 | 12 | protected: 13 | ShaderModule() = default; 14 | 15 | std::string label_; 16 | }; 17 | 18 | } // namespace Pathfinder 19 | 20 | #endif // PATHFINDER_GPU_SHADER_MODULE_H 21 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/fence.cpp: -------------------------------------------------------------------------------- 1 | #include "fence.h" 2 | 3 | #include "device.h" 4 | 5 | namespace Pathfinder { 6 | 7 | FenceGl::~FenceGl() { 8 | glDeleteSync(fence); 9 | } 10 | 11 | void FenceGl::wait() const { 12 | GLenum wait_result = glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); 13 | assert(wait_result == GL_ALREADY_SIGNALED || wait_result == GL_CONDITION_SATISFIED); 14 | } 15 | 16 | } // namespace Pathfinder 17 | -------------------------------------------------------------------------------- /demo/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Recursive search and automatic re-configuration on adding or deleting source files. 2 | file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp) 3 | 4 | # Compile as static library. 5 | add_library(pathfinder_demo_common STATIC ${SOURCE_FILES}) 6 | 7 | target_compile_features(pathfinder_demo_common PUBLIC cxx_std_14) 8 | 9 | # Include Pathfinder headers. 10 | target_include_directories(pathfinder_demo_common PUBLIC "../../") 11 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/fence.cpp: -------------------------------------------------------------------------------- 1 | #include "fence.h" 2 | 3 | #include "device.h" 4 | 5 | namespace Pathfinder { 6 | 7 | FenceVk::~FenceVk() { 8 | if (fence) { 9 | vkDestroyFence(device->get_device(), fence, nullptr); 10 | } 11 | } 12 | 13 | void FenceVk::wait() const { 14 | // Wait indefinitely 15 | vkWaitForFences(device->get_device(), 1, &fence, VK_TRUE, UINT64_MAX); 16 | vkResetFences(device->get_device(), 1, &fence); 17 | } 18 | 19 | } // namespace Pathfinder 20 | -------------------------------------------------------------------------------- /demo/android/app/src/main/java/graphics/pathfinder/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package graphics.pathfinder.demo; 2 | 3 | import com.google.androidgamesdk.GameActivity; 4 | 5 | import android.os.Bundle; 6 | 7 | public class MainActivity extends GameActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | } 13 | 14 | static { 15 | System.loadLibrary("pathfinder_android_demo"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/fence.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FENCE_GL_H 2 | #define PATHFINDER_GPU_FENCE_GL_H 3 | 4 | #include "../fence.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class FenceGl : public Fence { 10 | friend class DeviceGl; 11 | 12 | public: 13 | ~FenceGl(); 14 | 15 | void wait() const; 16 | 17 | private: 18 | FenceGl() = default; 19 | 20 | GLsync fence{}; 21 | }; 22 | 23 | } // namespace Pathfinder 24 | 25 | #endif // PATHFINDER_GPU_FENCE_GL_H 26 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/glfw3.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ 4 | libdir=@CMAKE_INSTALL_FULL_LIBDIR@ 5 | 6 | Name: GLFW 7 | Description: A multi-platform library for OpenGL, window and input 8 | Version: @GLFW_VERSION@ 9 | URL: https://www.glfw.org/ 10 | Requires.private: @GLFW_PKG_CONFIG_REQUIRES_PRIVATE@ 11 | Libs: -L${libdir} -l@GLFW_LIB_NAME@ 12 | Libs.private: @GLFW_PKG_CONFIG_LIBS_PRIVATE@ 13 | Cflags: -I${includedir} 14 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/render_pass.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PASS_GL_H 2 | #define PATHFINDER_GPU_RENDER_PASS_GL_H 3 | 4 | #include "../render_pass.h" 5 | 6 | namespace Pathfinder { 7 | 8 | class RenderPassGl : public RenderPass { 9 | friend class DeviceGl; 10 | friend class SwapChainGl; 11 | 12 | private: 13 | explicit RenderPassGl(AttachmentLoadOp load_op) { 14 | load_op_ = load_op; 15 | } 16 | }; 17 | 18 | } // namespace Pathfinder 19 | 20 | #endif // PATHFINDER_GPU_RENDER_PASS_GL_H 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | # NOTE: do not edit this file manually! Use git commands. 2 | 3 | # First time clone: 4 | # git submodule update --init --recursive 5 | 6 | # Update: 7 | # git pull --recurse-submodules | git submodule update --remote --recursive 8 | 9 | # Add submodule: 10 | # git submodule add [URL] [SUBMODULE_PATH] 11 | 12 | # Check status: 13 | # git submodule 14 | 15 | # See the submodule URLs: 16 | # git submodule foreach -q git config remote.origin.url 17 | 18 | # Set branch: 19 | # git submodule set-branch --branch [BRANCH_NAME] [SUBMODULE_PATH] 20 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/data/alpha_tile_id.cpp: -------------------------------------------------------------------------------- 1 | #include "alpha_tile_id.h" 2 | 3 | namespace Pathfinder { 4 | 5 | AlphaTileId::AlphaTileId(std::array, ALPHA_TILE_LEVEL_COUNT> &next_alpha_tile_index, int level) { 6 | // Atomic fetch & add. 7 | size_t alpha_tile_index = next_alpha_tile_index[level].fetch_add(1); 8 | 9 | value = level * ALPHA_TILES_PER_LEVEL + alpha_tile_index; 10 | } 11 | 12 | bool AlphaTileId::is_valid() const { 13 | return value < std::numeric_limits::max(); 14 | } 15 | 16 | } // namespace Pathfinder 17 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/modules/FindOSMesa.cmake: -------------------------------------------------------------------------------- 1 | # Try to find OSMesa on a Unix system 2 | # 3 | # This will define: 4 | # 5 | # OSMESA_LIBRARIES - Link these to use OSMesa 6 | # OSMESA_INCLUDE_DIR - Include directory for OSMesa 7 | # 8 | # Copyright (c) 2014 Brandon Schaefer 9 | 10 | if (NOT WIN32) 11 | 12 | find_package (PkgConfig) 13 | pkg_check_modules (PKG_OSMESA QUIET osmesa) 14 | 15 | set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS}) 16 | set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES}) 17 | 18 | endif () 19 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/fence.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FENCE_VK_H 2 | #define PATHFINDER_GPU_FENCE_VK_H 3 | 4 | #include "../fence.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class DeviceVk; 10 | 11 | class FenceVk : public Fence { 12 | friend class DeviceVk; 13 | friend class QueueVk; 14 | 15 | public: 16 | ~FenceVk(); 17 | 18 | void wait() const; 19 | 20 | private: 21 | FenceVk() = default; 22 | 23 | VkFence fence = VK_NULL_HANDLE; 24 | DeviceVk *device = nullptr; 25 | }; 26 | 27 | } // namespace Pathfinder 28 | 29 | #endif // PATHFINDER_GPU_FENCE_VK_H 30 | -------------------------------------------------------------------------------- /pathfinder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Recursive search and automatic re-configuration on adding or deleting source files. 2 | file(GLOB_RECURSE PF_SOURCE_FILES CONFIGURE_DEPENDS common/*.cpp core/*.cpp gpu_mem/*.cpp) 3 | 4 | file(GLOB PF_SOURCE_FILES ${PF_SOURCE_FILES} gpu/*.cpp) 5 | 6 | if (PATHFINDER_BACKEND_VULKAN) 7 | file(GLOB PF_SOURCE_FILES ${PF_SOURCE_FILES} gpu/vk/*.cpp) 8 | endif () 9 | 10 | if (PATHFINDER_BACKEND_OPENGL) 11 | file(GLOB PF_SOURCE_FILES ${PF_SOURCE_FILES} gpu/gl/*.cpp ../third_party/glad/src/gl.c) 12 | endif () 13 | 14 | # Compile as static library. 15 | add_library(pathfinder STATIC ${PF_SOURCE_FILES}) 16 | -------------------------------------------------------------------------------- /pathfinder/gpu/render_pass.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PASS_H 2 | #define PATHFINDER_GPU_RENDER_PASS_H 3 | 4 | #include "../common/math/vec2.h" 5 | 6 | namespace Pathfinder { 7 | 8 | enum class AttachmentLoadOp; 9 | 10 | class RenderPass { 11 | public: 12 | virtual ~RenderPass() = default; 13 | 14 | AttachmentLoadOp get_attachment_load_op() const { 15 | return load_op_; 16 | } 17 | 18 | protected: 19 | RenderPass() = default; 20 | 21 | AttachmentLoadOp load_op_; 22 | 23 | /// Debug label. 24 | std::string label_; 25 | }; 26 | 27 | } // namespace Pathfinder 28 | 29 | #endif // PATHFINDER_GPU_RENDER_PASS_H 30 | -------------------------------------------------------------------------------- /pathfinder/shaders/blit.frag: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | #ifdef GL_ES 4 | precision highp float; 5 | precision highp sampler2D; 6 | #endif 7 | 8 | #ifdef VULKAN 9 | layout(location = 0) out vec4 oFragColor; 10 | 11 | layout(location = 0) in vec2 vUV; 12 | 13 | layout(binding = 0) uniform sampler2D uTexture; 14 | #else 15 | out vec4 oFragColor; 16 | 17 | in vec2 vUV; 18 | 19 | uniform sampler2D uTexture; 20 | #endif 21 | 22 | void main() { 23 | // When drawing to the screen, we need to flip the texture for GL. 24 | #ifdef VULKAN 25 | oFragColor = texture(uTexture, vUV); 26 | #else 27 | oFragColor = texture(uTexture, vec2(vUV.x, 1.0f - vUV.y)); 28 | #endif 29 | } 30 | -------------------------------------------------------------------------------- /demo/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:8.12.0' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files. 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | mavenCentral() 20 | } 21 | } 22 | 23 | tasks.register('clean', Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/i686-w64-mingw32.cmake: -------------------------------------------------------------------------------- 1 | # Define the environment for cross-compiling with 32-bit MinGW-w64 GCC 2 | SET(CMAKE_SYSTEM_NAME Windows) # Target system name 3 | SET(CMAKE_SYSTEM_VERSION 1) 4 | SET(CMAKE_C_COMPILER "i686-w64-mingw32-gcc") 5 | SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++") 6 | SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres") 7 | SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib") 8 | 9 | # Configure the behaviour of the find commands 10 | SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32") 11 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 12 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 13 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 14 | -------------------------------------------------------------------------------- /pathfinder/prelude.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_PRELUDE_H 2 | #define PATHFINDER_PRELUDE_H 3 | 4 | #include "common/global_macros.h" 5 | #include "common/io.h" 6 | #include "common/logger.h" 7 | #include "common/math/basic.h" 8 | #include "common/math/mat3.h" 9 | #include "common/math/mat4.h" 10 | #include "common/math/rect.h" 11 | #include "common/math/vec2.h" 12 | #include "common/math/vec3.h" 13 | #include "common/timestamp.h" 14 | #include "core/canvas.h" 15 | #include "core/svg.h" 16 | #include "gpu/device.h" 17 | #include "gpu/framebuffer.h" 18 | #include "gpu/queue.h" 19 | #include "gpu/swap_chain.h" 20 | #include "gpu/window.h" 21 | #include "gpu/window_builder.h" 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/command_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_COMMAND_BUFFER_GL_H 2 | #define PATHFINDER_GPU_COMMAND_BUFFER_GL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../command_encoder.h" 9 | 10 | namespace Pathfinder { 11 | 12 | class CommandEncoderGl : public CommandEncoder { 13 | friend class DeviceGl; 14 | friend class SwapChainGl; 15 | 16 | public: 17 | ~CommandEncoderGl() override; 18 | 19 | private: 20 | CommandEncoderGl() = default; 21 | 22 | bool finish() override; 23 | 24 | std::vector vao_; 25 | }; 26 | 27 | } // namespace Pathfinder 28 | 29 | #endif // PATHFINDER_GPU_COMMAND_BUFFER_GL_H 30 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/i686-w64-mingw32-clang.cmake: -------------------------------------------------------------------------------- 1 | # Define the environment for cross-compiling with 32-bit MinGW-w64 Clang 2 | SET(CMAKE_SYSTEM_NAME Windows) # Target system name 3 | SET(CMAKE_SYSTEM_VERSION 1) 4 | SET(CMAKE_C_COMPILER "i686-w64-mingw32-clang") 5 | SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-clang++") 6 | SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres") 7 | SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib") 8 | 9 | # Configure the behaviour of the find commands 10 | SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32") 11 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 12 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 13 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 14 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/x86_64-w64-mingw32.cmake: -------------------------------------------------------------------------------- 1 | # Define the environment for cross-compiling with 64-bit MinGW-w64 GCC 2 | SET(CMAKE_SYSTEM_NAME Windows) # Target system name 3 | SET(CMAKE_SYSTEM_VERSION 1) 4 | SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc") 5 | SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++") 6 | SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres") 7 | SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib") 8 | 9 | # Configure the behaviour of the find commands 10 | SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32") 11 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 12 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 13 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 14 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/x86_64-w64-mingw32-clang.cmake: -------------------------------------------------------------------------------- 1 | # Define the environment for cross-compiling with 64-bit MinGW-w64 Clang 2 | SET(CMAKE_SYSTEM_NAME Windows) # Target system name 3 | SET(CMAKE_SYSTEM_VERSION 1) 4 | SET(CMAKE_C_COMPILER "x86_64-w64-mingw32-clang") 5 | SET(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-clang++") 6 | SET(CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres") 7 | SET(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib") 8 | 9 | # Configure the behaviour of the find commands 10 | SET(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32") 11 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 12 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 13 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 14 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/shader_module.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_SHADER_MODULE_VK_H 2 | #define PATHFINDER_GPU_SHADER_MODULE_VK_H 3 | 4 | namespace Pathfinder { 5 | 6 | class ShaderModuleVk : public ShaderModule { 7 | friend class DeviceVk; 8 | 9 | public: 10 | ~ShaderModuleVk() override { 11 | vkDestroyShaderModule(vk_device_, vk_shader_module_, nullptr); 12 | } 13 | 14 | VkShaderModule get_raw_handle() const { 15 | return vk_shader_module_; 16 | } 17 | 18 | private: 19 | ShaderModuleVk() = default; 20 | 21 | VkShaderModule vk_shader_module_{}; 22 | VkDevice vk_device_{}; 23 | }; 24 | 25 | } // namespace Pathfinder 26 | #endif // PATHFINDER_GPU_SHADER_MODULE_VK_H 27 | -------------------------------------------------------------------------------- /pathfinder/core/svg.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_SVG_H 2 | #define PATHFINDER_SVG_H 3 | 4 | #include "canvas.h" 5 | #include "scene.h" 6 | 7 | namespace Pathfinder { 8 | 9 | /// Analogy to a SVG image. 10 | class SvgScene { 11 | public: 12 | /** 13 | * @brief Load SVG string into the scene. 14 | * @param svg SVG file content, a copy by value is needed. 15 | * @param canvas Pathfinder Canvas. 16 | */ 17 | SvgScene(const std::string& svg, Canvas& canvas); 18 | 19 | std::shared_ptr get_scene() const; 20 | 21 | Vec2F get_size() const; 22 | 23 | private: 24 | std::shared_ptr scene_; 25 | 26 | Vec2F size_; 27 | }; 28 | 29 | } // namespace Pathfinder 30 | 31 | #endif // PATHFINDER_SVG_H 32 | -------------------------------------------------------------------------------- /pathfinder/common/math/unit_vector.cpp: -------------------------------------------------------------------------------- 1 | #include "unit_vector.h" 2 | 3 | namespace Pathfinder { 4 | 5 | UnitVector::UnitVector(float x, float y) : x(x), y(y) {} 6 | 7 | UnitVector::UnitVector(const Vec2F &vec) : x(vec.x), y(vec.y) {} 8 | 9 | UnitVector UnitVector::rotate_by(const UnitVector &other) const { 10 | return {x * other.x - y * other.y, y * other.x + x * other.y}; 11 | } 12 | 13 | UnitVector UnitVector::rev_rotate_by(const UnitVector &other) const { 14 | return {x * other.x + y * other.y, y * other.x - x * other.y}; 15 | } 16 | 17 | UnitVector UnitVector::halve_angle() const { 18 | auto term = Vec2F(x, -x); 19 | return UnitVector((Vec2F(0.5f) * (Vec2F(1.0f) + term)).max(Vec2F(0)).sqrt()); 20 | } 21 | 22 | } // namespace Pathfinder 23 | -------------------------------------------------------------------------------- /pathfinder/gpu/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_QUEUE_H 2 | #define PATHFINDER_GPU_QUEUE_H 3 | 4 | #include "../common/math/vec2.h" 5 | #include "command_encoder.h" 6 | #include "fence.h" 7 | #include "framebuffer.h" 8 | #include "render_pass.h" 9 | 10 | namespace Pathfinder { 11 | 12 | class SwapChain; 13 | 14 | /// Handle to a command queue on a device. 15 | class Queue { 16 | public: 17 | explicit Queue() = default; 18 | 19 | virtual ~Queue() = default; 20 | 21 | virtual void submit(const std::shared_ptr &encoder, const std::shared_ptr &fence) = 0; 22 | 23 | virtual void submit_and_wait(const std::shared_ptr &encoder) = 0; 24 | }; 25 | 26 | } // namespace Pathfinder 27 | 28 | #endif // PATHFINDER_GPU_QUEUE_H 29 | -------------------------------------------------------------------------------- /pathfinder/common/timestamp.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_TIMESTAMP_H 2 | #define PATHFINDER_TIMESTAMP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Pathfinder { 9 | 10 | class Timestamp { 11 | std::chrono::time_point start_time; 12 | 13 | std::vector records; // In ms. 14 | std::vector labels; 15 | 16 | bool enabled_ = true; 17 | 18 | std::string logger_tag_; 19 | 20 | public: 21 | Timestamp(const std::string &logger_tag); 22 | 23 | void record(const std::string &label); 24 | 25 | void reset(); 26 | 27 | void print() const; 28 | 29 | void set_enabled(bool enabled); 30 | }; 31 | 32 | } // namespace Pathfinder 33 | 34 | #endif // PATHFINDER_TIMESTAMP_H 35 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/compute_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_COMPUTE_PIPELINE_GL_H 2 | #define PATHFINDER_GPU_COMPUTE_PIPELINE_GL_H 3 | 4 | #include 5 | 6 | #include "../compute_pipeline.h" 7 | #include "program.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class ComputePipelineGl : public ComputePipeline { 12 | friend class DeviceGl; 13 | 14 | public: 15 | std::shared_ptr get_program() { 16 | return program_; 17 | } 18 | 19 | private: 20 | explicit ComputePipelineGl(const std::shared_ptr &comp_shader_module) { 21 | program_ = std::make_shared(comp_shader_module); 22 | } 23 | 24 | std::shared_ptr program_; 25 | }; 26 | 27 | } // namespace Pathfinder 28 | 29 | #endif // PATHFINDER_GPU_COMPUTE_PIPELINE_GL_H 30 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_BUFFER_GL_H 2 | #define PATHFINDER_GPU_BUFFER_GL_H 3 | 4 | #include 5 | 6 | #include "../buffer.h" 7 | 8 | namespace Pathfinder { 9 | 10 | class BufferGl : public Buffer { 11 | friend class DeviceGl; 12 | 13 | public: 14 | ~BufferGl() override; 15 | 16 | void upload_via_mapping(size_t data_size, size_t offset, const void* data) override; 17 | 18 | void download_via_mapping(size_t data_size, size_t offset, void* data) override; 19 | 20 | uint32_t get_handle() const; 21 | 22 | void set_label(const std::string& label) override; 23 | 24 | private: 25 | explicit BufferGl(const BufferDescriptor& desc); 26 | 27 | uint32_t gl_id_ = 0; 28 | }; 29 | 30 | } // namespace Pathfinder 31 | 32 | #endif // PATHFINDER_GPU_BUFFER_GL_H 33 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/render_pass.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PASS_VK_H 2 | #define PATHFINDER_GPU_RENDER_PASS_VK_H 3 | 4 | #include "../render_pass.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class RenderPassVk : public RenderPass { 10 | friend class DeviceVk; 11 | 12 | public: 13 | ~RenderPassVk() override; 14 | 15 | VkRenderPass get_vk_render_pass(); 16 | 17 | private: 18 | RenderPassVk(VkDevice vk_device, 19 | TextureFormat texture_format, 20 | AttachmentLoadOp load_op, 21 | bool is_swap_chain_pass, 22 | const std::string &label); 23 | 24 | VkRenderPass vk_render_pass_{}; 25 | 26 | VkDevice vk_device_{}; 27 | }; 28 | 29 | } // namespace Pathfinder 30 | 31 | #endif // PATHFINDER_GPU_RENDER_PASS_VK_H 32 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/shader_module.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_SHADER_MODULE_GL_H 2 | #define PATHFINDER_GPU_SHADER_MODULE_GL_H 3 | 4 | #include 5 | 6 | #include "../shader_module.h" 7 | 8 | namespace Pathfinder { 9 | 10 | enum class ShaderStage; 11 | 12 | class ShaderModuleGl : public ShaderModule { 13 | friend class DeviceGl; 14 | 15 | public: 16 | ~ShaderModuleGl() override; 17 | 18 | unsigned int get_handle() const; 19 | 20 | private: 21 | ShaderModuleGl(const std::vector& source_code, ShaderStage shader_stage, const std::string& label = ""); 22 | 23 | /// Utility function for checking shader compilation errors. 24 | void check_compile_errors() const; 25 | 26 | unsigned int id_{}; 27 | }; 28 | 29 | } // namespace Pathfinder 30 | 31 | #endif // PATHFINDER_GPU_SHADER_MODULE_GL_H 32 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/texture.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_TEXTURE_GL_H 2 | #define PATHFINDER_GPU_TEXTURE_GL_H 3 | 4 | #include "../texture.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | /// Use Texture via smart pointers as its de-constructor will release its GL resources. 10 | class TextureGl : public Texture { 11 | friend class DeviceGl; 12 | 13 | public: 14 | ~TextureGl() override; 15 | 16 | uint32_t get_texture_id() const; 17 | 18 | void set_label(const std::string& label) override; 19 | 20 | private: 21 | explicit TextureGl(const TextureDescriptor& desc); 22 | 23 | TextureGl(uint32_t external_gl_id, const TextureDescriptor& desc); 24 | 25 | bool wrapped = false; 26 | 27 | uint32_t gl_id_ = 0; 28 | }; 29 | 30 | } // namespace Pathfinder 31 | 32 | #endif // PATHFINDER_GPU_TEXTURE_GL_H 33 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/framebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FRAMEBUFFER_GL_H 2 | #define PATHFINDER_GPU_FRAMEBUFFER_GL_H 3 | 4 | #include 5 | 6 | #include "../framebuffer.h" 7 | #include "texture.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class FramebufferGl : public Framebuffer { 12 | friend class DeviceGl; 13 | friend class SwapChainGl; 14 | 15 | public: 16 | ~FramebufferGl() override; 17 | 18 | uint32_t get_gl_handle() const; 19 | 20 | void set_label(const std::string& label) override; 21 | 22 | private: 23 | /// Texture framebuffer. 24 | explicit FramebufferGl(const std::shared_ptr& texture); 25 | 26 | /// Swap chain framebuffer. 27 | FramebufferGl(); 28 | 29 | uint32_t gl_framebuffer_{}; 30 | }; 31 | 32 | } // namespace Pathfinder 33 | 34 | #endif // PATHFINDER_GPU_FRAMEBUFFER_GL_H 35 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/data/alpha_tile_id.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D9_ALPHA_TILE_ID_H 2 | #define PATHFINDER_D3D9_ALPHA_TILE_ID_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace Pathfinder { 11 | 12 | const size_t ALPHA_TILE_LEVEL_COUNT = 2; 13 | const size_t ALPHA_TILES_PER_LEVEL = 1 << (32 - ALPHA_TILE_LEVEL_COUNT + 1); 14 | 15 | struct AlphaTileId { 16 | /// A valid value means a solid tile. Default is invalid. 17 | uint32_t value = std::numeric_limits::max(); 18 | 19 | AlphaTileId() = default; 20 | 21 | AlphaTileId(std::array, ALPHA_TILE_LEVEL_COUNT> &next_alpha_tile_index, int level); 22 | 23 | bool is_valid() const; 24 | }; 25 | 26 | } // namespace Pathfinder 27 | 28 | #endif // PATHFINDER_D3D9_ALPHA_TILE_ID_H 29 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/modules/FindEpollShim.cmake: -------------------------------------------------------------------------------- 1 | # Find EpollShim 2 | # Once done, this will define 3 | # 4 | # EPOLLSHIM_FOUND - System has EpollShim 5 | # EPOLLSHIM_INCLUDE_DIRS - The EpollShim include directories 6 | # EPOLLSHIM_LIBRARIES - The libraries needed to use EpollShim 7 | 8 | find_path(EPOLLSHIM_INCLUDE_DIRS NAMES sys/epoll.h sys/timerfd.h HINTS /usr/local/include/libepoll-shim) 9 | find_library(EPOLLSHIM_LIBRARIES NAMES epoll-shim libepoll-shim HINTS /usr/local/lib) 10 | 11 | if (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) 12 | set(EPOLLSHIM_FOUND TRUE) 13 | endif (EPOLLSHIM_INCLUDE_DIRS AND EPOLLSHIM_LIBRARIES) 14 | 15 | include(FindPackageHandleStandardArgs) 16 | find_package_handle_standard_args(EpollShim DEFAULT_MSG EPOLLSHIM_LIBRARIES EPOLLSHIM_INCLUDE_DIRS) 17 | mark_as_advanced(EPOLLSHIM_INCLUDE_DIRS EPOLLSHIM_LIBRARIES) 18 | -------------------------------------------------------------------------------- /pathfinder/common/math/unit_vector.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_UNIT_VECTOR_H 2 | #define PATHFINDER_UNIT_VECTOR_H 3 | 4 | #include 5 | 6 | #include "vec2.h" 7 | 8 | namespace Pathfinder { 9 | 10 | struct UnitVector { 11 | float x; 12 | float y; 13 | 14 | UnitVector(float x, float y); 15 | 16 | explicit UnitVector(const Vec2F &vec); 17 | 18 | static UnitVector from_angle(float theta) { 19 | return {std::cos(theta), std::sin(theta)}; 20 | } 21 | 22 | /// Angle addition formula. 23 | UnitVector rotate_by(const UnitVector &other) const; 24 | 25 | /// Angle subtraction formula. 26 | UnitVector rev_rotate_by(const UnitVector &other) const; 27 | 28 | /// Half angle formula. 29 | UnitVector halve_angle() const; 30 | }; 31 | 32 | } // namespace Pathfinder 33 | 34 | #endif // PATHFINDER_UNIT_VECTOR_H 35 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/descriptor_set.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_DESCRIPTOR_SET_VK_H 2 | #define PATHFINDER_GPU_DESCRIPTOR_SET_VK_H 3 | 4 | #include "../descriptor_set.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class DescriptorSetVk : public DescriptorSet { 10 | friend class DeviceVk; 11 | 12 | public: 13 | ~DescriptorSetVk() override; 14 | 15 | void update_vk_descriptor_set(VkDevice vk_device, VkDescriptorSetLayout vk_descriptor_set_layout); 16 | 17 | VkDescriptorSet &get_vk_descriptor_set(); 18 | 19 | private: 20 | DescriptorSetVk() = default; 21 | 22 | VkDescriptorPool vk_descriptor_pool_{}; 23 | VkDescriptorSet vk_descriptor_set_{}; 24 | 25 | bool descriptor_set_allocated_ = false; 26 | 27 | VkDevice vk_device_{}; 28 | }; 29 | 30 | } // namespace Pathfinder 31 | 32 | #endif // PATHFINDER_GPU_DESCRIPTOR_SET_VK_H 33 | -------------------------------------------------------------------------------- /third_party/glfw/src/glfw.rc.in: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | VS_VERSION_INFO VERSIONINFO 5 | FILEVERSION @GLFW_VERSION_MAJOR@,@GLFW_VERSION_MINOR@,@GLFW_VERSION_PATCH@,0 6 | PRODUCTVERSION @GLFW_VERSION_MAJOR@,@GLFW_VERSION_MINOR@,@GLFW_VERSION_PATCH@,0 7 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 8 | FILEFLAGS 0 9 | FILEOS VOS_NT_WINDOWS32 10 | FILETYPE VFT_DLL 11 | FILESUBTYPE 0 12 | { 13 | BLOCK "StringFileInfo" 14 | { 15 | BLOCK "040904B0" 16 | { 17 | VALUE "CompanyName", "GLFW" 18 | VALUE "FileDescription", "GLFW @GLFW_VERSION@ DLL" 19 | VALUE "FileVersion", "@GLFW_VERSION@" 20 | VALUE "OriginalFilename", "glfw3.dll" 21 | VALUE "ProductName", "GLFW" 22 | VALUE "ProductVersion", "@GLFW_VERSION@" 23 | } 24 | } 25 | BLOCK "VarFileInfo" 26 | { 27 | VALUE "Translation", 0x409, 1200 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /demo/common/app.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_DEMO_APP_H 2 | #define PATHFINDER_DEMO_APP_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "blit.h" 9 | 10 | class App { 11 | public: 12 | App(const std::shared_ptr &device, 13 | const std::shared_ptr &queue, 14 | const Pathfinder::Vec2I &canvas_size, 15 | const std::vector &svg_input, 16 | const std::vector &img_input); 17 | 18 | void update(); 19 | 20 | void destroy(); 21 | 22 | std::shared_ptr canvas_; 23 | 24 | std::shared_ptr scene_0_, scene_1_; 25 | 26 | std::shared_ptr device_; 27 | std::shared_ptr queue_; 28 | 29 | private: 30 | std::chrono::time_point last_time_; 31 | uint32_t frame_count_ = 0; 32 | }; 33 | 34 | #endif // PATHFINDER_DEMO_APP_H 35 | -------------------------------------------------------------------------------- /pathfinder/core/data/path.cpp: -------------------------------------------------------------------------------- 1 | #include "path.h" 2 | 3 | #include "../../common/math/basic.h" 4 | 5 | namespace Pathfinder { 6 | 7 | void Outline::transform(const Transform2 &transform) { 8 | if (transform.is_identity()) { 9 | return; 10 | } 11 | 12 | RectF new_bounds; 13 | 14 | for (auto &contour : contours) { 15 | contour.transform(transform); 16 | 17 | // Update bounds. 18 | new_bounds = new_bounds.union_rect(contour.bounds); 19 | } 20 | 21 | bounds = new_bounds; 22 | } 23 | 24 | void Outline::push_contour(const Contour &_contour) { 25 | if (_contour.is_empty()) { 26 | return; 27 | } 28 | 29 | // Push contour. 30 | contours.push_back(_contour); 31 | 32 | // Update bounds. 33 | if (contours.empty()) { 34 | bounds = _contour.bounds; 35 | } else { 36 | bounds = bounds.union_rect(_contour.bounds); 37 | } 38 | } 39 | 40 | } // namespace Pathfinder 41 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d9/tile_clip_copy.frag: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | // pathfinder/shaders/tile_clip_copy.fs.glsl 4 | // 5 | // Copyright © 2020 The Pathfinder Project Developers. 6 | // 7 | // Licensed under the Apache License, Version 2.0 or the MIT license 9 | // , at your 10 | // option. This file may not be copied, modified, or distributed 11 | // except according to those terms. 12 | 13 | precision highp float; 14 | 15 | #ifdef GL_ES 16 | precision highp sampler2D; 17 | #endif 18 | 19 | #ifdef VULKAN 20 | layout(binding = 1) uniform sampler2D uSrc; 21 | 22 | layout(location = 0) in vec2 vTexCoord; 23 | 24 | layout(location = 0) out vec4 oFragColor; 25 | #else 26 | uniform sampler2D uSrc; 27 | 28 | in vec2 vTexCoord; 29 | 30 | out vec4 oFragColor; 31 | #endif 32 | 33 | void main() { 34 | oFragColor = texture(uSrc, vTexCoord); 35 | } 36 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/window.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_WINDOW_GL_H 2 | #define PATHFINDER_GPU_WINDOW_GL_H 3 | 4 | #ifdef __ANDROID__ 5 | #include 6 | #endif 7 | 8 | #include "../window.h" 9 | 10 | struct GLFWwindow; 11 | 12 | namespace Pathfinder { 13 | 14 | class WindowGl : public Window { 15 | friend class WindowBuilderGl; 16 | 17 | public: 18 | #ifndef __ANDROID__ 19 | WindowGl(const Vec2I &size, GLFWwindow *window_handle); 20 | #else 21 | WindowGl(const Vec2I &size, EGLDisplay egl_display, EGLSurface egl_surface, EGLContext egl_context); 22 | #endif 23 | 24 | std::shared_ptr get_swap_chain(const std::shared_ptr &device) override; 25 | 26 | private: 27 | void destroy() override; 28 | 29 | #ifdef __ANDROID__ 30 | EGLDisplay egl_display_; 31 | EGLSurface egl_surface_; 32 | EGLContext egl_context_; 33 | #endif 34 | }; 35 | 36 | } // namespace Pathfinder 37 | 38 | #endif // PATHFINDER_GPU_WINDOW_GL_H 39 | -------------------------------------------------------------------------------- /pathfinder/common/math/vec3.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_VEC3_H 2 | #define PATHFINDER_VEC3_H 3 | 4 | #include "vec2.h" 5 | 6 | namespace Pathfinder { 7 | 8 | template 9 | struct Vec3 { 10 | T x = 0; 11 | T y = 0; 12 | T z = 0; 13 | 14 | Vec3() = default; 15 | 16 | explicit Vec3(T s) : x(s), y(s), z(s){}; 17 | 18 | Vec3(T x, T y, T z) : x(x), y(y), z(z){}; 19 | 20 | Vec3(Vec2 v, T z) : x(v.x), y(v.y), z(z){}; 21 | 22 | Vec2 xy() const { 23 | return {x, y}; 24 | } 25 | 26 | Vec3 operator*(T s) const { 27 | return {x * s, y * s, z * s}; 28 | } 29 | 30 | bool operator==(const Vec3 &b) const { 31 | return x == b.x && y == b.y && z == b.z; 32 | } 33 | 34 | void operator+=(const Vec3 &b) { 35 | x += b.x; 36 | y += b.y; 37 | z += b.z; 38 | } 39 | }; 40 | 41 | typedef Vec3 Vec3F; 42 | 43 | } // namespace Pathfinder 44 | 45 | #endif // PATHFINDER_VEC3_H 46 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/command_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_COMMAND_BUFFER_VK_H 2 | #define PATHFINDER_GPU_COMMAND_BUFFER_VK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../command_encoder.h" 9 | #include "device.h" 10 | 11 | namespace Pathfinder { 12 | 13 | class CommandEncoderVk : public CommandEncoder { 14 | friend class DeviceVk; 15 | friend class QueueVk; 16 | friend class SwapChainVk; 17 | 18 | public: 19 | ~CommandEncoderVk() override; 20 | 21 | VkCommandBuffer get_vk_handle() const; 22 | 23 | private: 24 | CommandEncoderVk(VkCommandBuffer vk_command_buffer, DeviceVk *device); 25 | 26 | void sync_descriptor_set(DescriptorSet *descriptor_set); 27 | 28 | bool finish() override; 29 | 30 | VkCommandBuffer vk_command_buffer_{}; 31 | 32 | VkDevice vk_device_{}; 33 | 34 | DeviceVk *device_vk_{}; 35 | }; 36 | 37 | } // namespace Pathfinder 38 | 39 | #endif // PATHFINDER_GPU_COMMAND_BUFFER_VK_H 40 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_QUEUE_VK_H 2 | #define PATHFINDER_GPU_QUEUE_VK_H 3 | 4 | #include "../queue.h" 5 | #include "swap_chain.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class QueueVk : public Queue { 10 | friend class WindowVk; 11 | friend class WindowBuilderVk; 12 | 13 | public: 14 | void submit(const std::shared_ptr &encoder, const std::shared_ptr &fence) override; 15 | 16 | void submit_and_wait(const std::shared_ptr &encoder) override; 17 | 18 | private: 19 | VkDevice vk_device_{}; 20 | 21 | VkQueue vk_graphics_queue_{}; 22 | 23 | VkQueue vk_present_queue_{}; 24 | 25 | public: 26 | QueueVk(VkDevice vk_device, VkQueue vk_graphics_queue, VkQueue vk_present_queue) { 27 | vk_device_ = vk_device; 28 | vk_graphics_queue_ = vk_graphics_queue; 29 | vk_present_queue_ = vk_present_queue; 30 | } 31 | }; 32 | 33 | } // namespace Pathfinder 34 | 35 | #endif // PATHFINDER_GPU_QUEUE_VK_H 36 | -------------------------------------------------------------------------------- /third_party/glfw/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2006 Marcus Geelnard 2 | 3 | Copyright (c) 2006-2019 Camilla Löwy 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product documentation would 16 | be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and must not 19 | be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | 24 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/framebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FRAMEBUFFER_VK_H 2 | #define PATHFINDER_GPU_FRAMEBUFFER_VK_H 3 | 4 | #include 5 | 6 | #include "../framebuffer.h" 7 | #include "texture.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class FramebufferVk : public Framebuffer { 12 | friend class DeviceVk; 13 | friend class SwapChainVk; 14 | 15 | public: 16 | ~FramebufferVk() override; 17 | 18 | VkFramebuffer get_vk_handle() const; 19 | 20 | void set_label(const std::string& label) override; 21 | 22 | private: 23 | /// Texture framebuffer. 24 | FramebufferVk(VkDevice vk_device, VkRenderPass vk_render_pass, const std::shared_ptr& texture); 25 | 26 | /// Swap chain framebuffer. 27 | FramebufferVk(VkDevice vk_device, VkRenderPass vk_render_pass, Vec2I size, VkImageView vk_image_view); 28 | 29 | VkFramebuffer vk_framebuffer_{}; 30 | 31 | VkDevice vk_device_{}; 32 | }; 33 | 34 | } // namespace Pathfinder 35 | 36 | #endif // PATHFINDER_GPU_FRAMEBUFFER_VK_H 37 | -------------------------------------------------------------------------------- /pathfinder/core/dash.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_DASH_H 2 | #define PATHFINDER_DASH_H 3 | 4 | #include "data/path.h" 5 | 6 | namespace Pathfinder { 7 | 8 | struct DashState { 9 | Contour output; 10 | std::vector dashes; 11 | size_t current_dash_index; 12 | float distance_left; 13 | 14 | DashState(const std::vector &_dashes, float _offset); 15 | 16 | bool is_on() const; 17 | }; 18 | 19 | /// Transforms a stroke into a dashed stroke. 20 | struct OutlineDash { 21 | Outline &input; 22 | Outline output; 23 | DashState state; 24 | 25 | OutlineDash(Outline &_input, const std::vector &dashes, float offset); 26 | 27 | void dash(); 28 | 29 | Outline into_outline(); 30 | }; 31 | 32 | struct ContourDash { 33 | Contour &input; 34 | Outline &output; 35 | DashState &state; 36 | 37 | ContourDash(Contour &_input, Outline &_output, DashState &_state); 38 | 39 | void dash(); 40 | }; 41 | 42 | } // namespace Pathfinder 43 | 44 | #endif // PATHFINDER_DASH_H 45 | -------------------------------------------------------------------------------- /demo/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 13 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /pathfinder/gpu/render_api.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_NATIVE_RENDER_API_H 2 | #define PATHFINDER_NATIVE_RENDER_API_H 3 | 4 | #ifdef __ANDROID__ 5 | #ifdef PATHFINDER_USE_OPENGL 6 | 7 | #ifdef PATHFINDER_ENABLE_D3D11 8 | #include 9 | #else 10 | #include 11 | #endif 12 | 13 | #endif 14 | 15 | #ifdef PATHFINDER_USE_VULKAN 16 | // Vulkan header. 17 | #include "vulkan_wrapper.h" 18 | #endif 19 | 20 | #elif defined(__EMSCRIPTEN__) 21 | #define GLFW_INCLUDE_ES3 22 | #include 23 | #else // Native 24 | 25 | #ifdef PATHFINDER_USE_OPENGL 26 | // Include OpenGL header via GLAD. 27 | #include 28 | #define GLFW_INCLUDE_NONE 29 | #endif 30 | 31 | #ifdef PATHFINDER_USE_VULKAN 32 | #define GLFW_INCLUDE_VULKAN 33 | #include 34 | #endif 35 | 36 | #include 37 | 38 | #endif 39 | 40 | #endif // PATHFINDER_NATIVE_RENDER_API_H 41 | -------------------------------------------------------------------------------- /pathfinder/core/scene_builder.cpp: -------------------------------------------------------------------------------- 1 | #include "renderer.h" 2 | 3 | namespace Pathfinder { 4 | 5 | bool fixup_batch_for_new_path_if_possible(std::shared_ptr &batch_color_texture, 6 | const BuiltDrawPath &draw_path) { 7 | // Check if the new draw path has a color texture. 8 | if (draw_path.color_texture_info) { 9 | // If the current batch doesn't have a color texture. 10 | if (batch_color_texture == nullptr) { 11 | // Update batch color texture. 12 | batch_color_texture = draw_path.color_texture_info; 13 | return true; 14 | } 15 | 16 | // If the current batch has a different color texture than that of the draw path. 17 | if (*draw_path.color_texture_info != *batch_color_texture) { 18 | Logger::debug("Batch break: path color texture mismatches batch color texture!"); 19 | return false; 20 | } 21 | } 22 | return true; 23 | } 24 | 25 | } // namespace Pathfinder 26 | -------------------------------------------------------------------------------- /pathfinder/core/scene_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_SCENE_BUILDER_H 2 | #define PATHFINDER_SCENE_BUILDER_H 3 | 4 | #include "data/built_path.h" 5 | 6 | namespace Pathfinder { 7 | 8 | /// Check if we need a new batch due to color texture change. 9 | bool fixup_batch_for_new_path_if_possible(std::shared_ptr& batch_color_texture, 10 | const BuiltDrawPath& draw_path); 11 | 12 | class Scene; 13 | 14 | class Renderer; 15 | 16 | /// Build a scene on the CPU side for rendering. 17 | class SceneBuilder { 18 | public: 19 | SceneBuilder() = default; 20 | 21 | virtual ~SceneBuilder() = default; 22 | 23 | /// Build everything we need for rendering. 24 | virtual void build(Scene* _scene, Renderer* renderer) = 0; 25 | 26 | Scene* get_scene() const { 27 | return scene; 28 | } 29 | 30 | protected: 31 | // Use a raw pointer to avoid cyclic reference. 32 | Scene* scene{}; 33 | }; 34 | 35 | } // namespace Pathfinder 36 | 37 | #endif // PATHFINDER_SCENE_BUILDER_H 38 | -------------------------------------------------------------------------------- /demo/android/app/src/main/cpp/native_engine.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class NativeEngine { 10 | public: 11 | explicit NativeEngine(android_app *app) { 12 | mAppCtx = app; 13 | } 14 | 15 | ~NativeEngine() = default; 16 | 17 | bool init_app(bool use_vulkan); 18 | 19 | void draw_frame(); 20 | 21 | bool is_ready() const; 22 | 23 | protected: 24 | void init_app_common(Pathfinder::Vec2I window_size); 25 | 26 | android_app *mAppCtx; 27 | 28 | std::shared_ptr pf_app; 29 | std::shared_ptr pf_blit; 30 | 31 | std::shared_ptr window_builder; 32 | std::shared_ptr pf_window; 33 | std::shared_ptr pf_device; 34 | std::shared_ptr pf_queue; 35 | std::shared_ptr pf_swapchain; 36 | }; 37 | -------------------------------------------------------------------------------- /demo/android/app/src/main/cpp/GameActivitySources.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // GameActivity's C/C++ code 16 | #include 17 | #include 18 | 19 | // Glue from GameActivity to android_main() 20 | // Passing GameActivity event from main thread to app native thread. 21 | extern "C" { 22 | #include 23 | } 24 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/window.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_WINDOW_VK_H 2 | #define PATHFINDER_GPU_WINDOW_VK_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../../common/global_macros.h" 9 | #include "../window.h" 10 | #include "device.h" 11 | 12 | namespace Pathfinder { 13 | 14 | class WindowVk : public Window { 15 | friend class WindowBuilderVk; 16 | 17 | public: 18 | #ifndef __ANDROID__ 19 | explicit WindowVk(const Vec2I &_size, GLFWwindow *window_handle, VkSurfaceKHR surface, VkInstance instance); 20 | #else 21 | explicit WindowVk(const Vec2I &_size, VkSurfaceKHR surface, VkInstance instance); 22 | #endif 23 | 24 | VkExtent2D choose_swap_extent(const VkSurfaceCapabilitiesKHR &capabilities) const; 25 | 26 | std::shared_ptr get_swap_chain(const std::shared_ptr &device) override; 27 | 28 | VkSurfaceKHR surface_{}; 29 | 30 | VkInstance instance_{}; 31 | 32 | private: 33 | void destroy() override; 34 | }; 35 | 36 | } // namespace Pathfinder 37 | 38 | #endif // PATHFINDER_GPU_WINDOW_VK_H 39 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/blit_vert.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_BLIT_VERT_H 2 | #define PATHFINDER_RESOURCE_BLIT_VERT_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t blit_vert[] = {35,118,101,114,115,105,111,110,32,51,49,48,32,101,115,13,10,13,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,118,101,99,50,32,97,80,111,115,59,13,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,49,41,32,105,110,32,118,101,99,50,32,97,85,86,59,13,10,13,10,35,105,102,100,101,102,32,86,85,76,75,65,78,13,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,50,32,118,85,86,59,13,10,35,101,108,115,101,13,10,111,117,116,32,118,101,99,50,32,118,85,86,59,13,10,35,101,110,100,105,102,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,32,123,13,10,32,32,32,32,118,85,86,32,61,32,97,85,86,59,13,10,13,10,32,32,32,32,103,108,95,80,111,115,105,116,105,111,110,32,61,32,118,101,99,52,40,97,80,111,115,44,32,48,46,48,44,32,49,46,48,41,59,13,10,125,13,10}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_BLIT_VERT_H 9 | -------------------------------------------------------------------------------- /pathfinder/common/io.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_IO_H 2 | #define PATHFINDER_IO_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "color.h" 12 | #include "math/vec2.h" 13 | 14 | namespace Pathfinder { 15 | 16 | #ifndef __ANDROID__ 17 | std::vector load_file_as_bytes(const std::string &file_path); 18 | 19 | std::string load_file_as_string(const std::string &file_path); 20 | #else 21 | 22 | std::vector load_asset(void *asset_manager, const std::string &filename); 23 | #endif 24 | 25 | class ImageBuffer { 26 | public: 27 | ~ImageBuffer(); 28 | 29 | static std::shared_ptr from_memory(const std::vector &bytes, bool flip_y); 30 | 31 | std::vector to_rgba_pixels() const; 32 | 33 | Vec2I get_size() const; 34 | 35 | unsigned char *get_data() const; 36 | 37 | private: 38 | Vec2I size; 39 | 40 | int32_t channel_count{}; 41 | 42 | unsigned char *data{}; 43 | }; 44 | 45 | } // namespace Pathfinder 46 | 47 | #endif // PATHFINDER_IO_H 48 | -------------------------------------------------------------------------------- /demo/common/blit.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_DEMO_TEXTURE_RECT_H 2 | #define PATHFINDER_DEMO_TEXTURE_RECT_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | /// Simplly blits a texture to screen. 9 | class Blit { 10 | public: 11 | Blit(const std::shared_ptr &device, 12 | const std::shared_ptr &queue, 13 | Pathfinder::TextureFormat target_format); 14 | 15 | void set_texture(const std::shared_ptr &new_texture); 16 | 17 | void draw(const std::shared_ptr &encoder); 18 | 19 | private: 20 | std::shared_ptr device_; 21 | 22 | std::shared_ptr queue_; 23 | 24 | std::shared_ptr texture_; 25 | 26 | std::shared_ptr pipeline_; 27 | 28 | std::shared_ptr vertex_buffer_; 29 | 30 | std::shared_ptr descriptor_set_; 31 | 32 | std::shared_ptr sampler_; 33 | }; 34 | 35 | #endif // PATHFINDER_DEMO_TEXTURE_RECT_H 36 | -------------------------------------------------------------------------------- /pathfinder/common/math/transform2.cpp: -------------------------------------------------------------------------------- 1 | #include "transform2.h" 2 | 3 | namespace Pathfinder { 4 | 5 | Transform2::Transform2() { 6 | *this = from_scale(Vec2F(1)); 7 | } 8 | 9 | Transform2::Transform2(float xform[6]) { 10 | matrix = {xform[0], xform[1], xform[2], xform[3]}; 11 | vector = {xform[4], xform[5]}; 12 | } 13 | 14 | Transform2::Transform2(const Mat2 &matrix, const Vec2F &vector) : matrix(matrix), vector(vector) {} 15 | 16 | Transform2 Transform2::translate(const Vec2F &_vector) const { 17 | return from_translation(_vector) * *this; 18 | } 19 | 20 | Transform2 Transform2::rotate(float theta) const { 21 | return from_rotation(theta) * *this; 22 | } 23 | 24 | bool Transform2::is_identity() const { 25 | return matrix == Mat2::from_scale({1, 1}) && vector == Vec2F(); 26 | } 27 | 28 | Transform2 Transform2::inverse() const { 29 | auto matrix_inv = matrix.inverse(); 30 | auto vector_inv = -(matrix_inv * vector); 31 | return {matrix_inv, vector_inv}; 32 | } 33 | 34 | Vec2F Transform2::get_position() const { 35 | return vector; 36 | } 37 | 38 | } // namespace Pathfinder 39 | -------------------------------------------------------------------------------- /pathfinder/core/paint/pattern.cpp: -------------------------------------------------------------------------------- 1 | #include "pattern.h" 2 | 3 | namespace Pathfinder { 4 | 5 | bool Pattern::repeat_x() const { 6 | return (flags.value & PatternFlags::REPEAT_X) != 0x0; 7 | } 8 | 9 | void Pattern::set_repeat_x(bool repeat_x) { 10 | if (repeat_x) { 11 | flags.value |= PatternFlags::REPEAT_X; 12 | } else { 13 | flags.value &= ~PatternFlags::REPEAT_X; 14 | } 15 | } 16 | 17 | bool Pattern::repeat_y() const { 18 | return (flags.value & PatternFlags::REPEAT_Y) != 0x0; 19 | } 20 | 21 | void Pattern::set_repeat_y(bool repeat_y) { 22 | if (repeat_y) { 23 | flags.value |= PatternFlags::REPEAT_Y; 24 | } else { 25 | flags.value &= ~PatternFlags::REPEAT_Y; 26 | } 27 | } 28 | 29 | bool Pattern::smoothing_enabled() const { 30 | return (flags.value & PatternFlags::NO_SMOOTHING) == 0x0; 31 | } 32 | 33 | void Pattern::set_smoothing_enabled(bool enable) { 34 | if (!enable) { 35 | flags.value |= PatternFlags::NO_SMOOTHING; 36 | } else { 37 | flags.value &= ~PatternFlags::NO_SMOOTHING; 38 | } 39 | } 40 | 41 | } // namespace Pathfinder 42 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/data/gpu_data.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D9_GPU_DATA_H 2 | #define PATHFINDER_D3D9_GPU_DATA_H 3 | 4 | #include "../../data/line_segment.h" 5 | #include "alpha_tile_id.h" 6 | 7 | namespace Pathfinder { 8 | 9 | //! Data that will be sent to GPU directly. 10 | 11 | /// A vector of this will be sent to the fill program. 12 | struct Fill { 13 | LineSegmentU16 line_segment; 14 | 15 | /// Index of the alpha tile that this fill belongs to. 16 | uint32_t link; 17 | }; 18 | 19 | /// A vector of this will be sent the tile program. 20 | struct TileObjectPrimitive { 21 | int16_t tile_x = 0; 22 | int16_t tile_y = 0; 23 | AlphaTileId alpha_tile_id; 24 | uint8_t ctrl = 0; // Fill rule 25 | int8_t backdrop = 0; 26 | uint32_t path_id = 0; 27 | uint32_t metadata_id = 0; 28 | }; 29 | 30 | /// A vector of this will be sent the tile clip copy program. 31 | struct Clip { 32 | AlphaTileId dest_tile_id; 33 | int32_t dest_backdrop = 0; 34 | AlphaTileId src_tile_id; 35 | int32_t src_backdrop = 0; 36 | }; 37 | 38 | } // namespace Pathfinder 39 | 40 | #endif // PATHFINDER_D3D9_GPU_DATA_H 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 floppyhammer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/data/draw_tile_batch.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D9_DRAW_TILE_BATCH_H 2 | #define PATHFINDER_D3D9_DRAW_TILE_BATCH_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../../data/data.h" 8 | #include "../../data/dense_tile_map.h" 9 | #include "../../paint/effects.h" 10 | #include "../../paint/paint.h" 11 | #include "gpu_data.h" 12 | 13 | namespace Pathfinder { 14 | 15 | /// Tiles in a batch use the same color texture and render target. 16 | struct DrawTileBatchD3D9 { 17 | std::vector tiles; 18 | 19 | std::vector clips; 20 | 21 | // Tile map size = viewport size / tile size. 22 | DenseTileMap z_buffer_data; 23 | 24 | /// The color texture to use. 25 | std::shared_ptr color_texture_info; 26 | 27 | /// Render target ID. 28 | std::shared_ptr render_target_id; 29 | 30 | /// The filter to use. 31 | // Filter filter; 32 | 33 | /// The blend mode to composite these tiles with. 34 | BlendMode blend_mode; 35 | }; 36 | 37 | } // namespace Pathfinder 38 | 39 | #endif // PATHFINDER_D3D9_DRAW_TILE_BATCH_H 40 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/window_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_WINDOW_BUILDER_GL_H 2 | #define PATHFINDER_WINDOW_BUILDER_GL_H 3 | 4 | #include "../window_builder.h" 5 | 6 | struct GLFWwindow; 7 | 8 | namespace Pathfinder { 9 | 10 | class Window; 11 | 12 | class WindowBuilderGl : public WindowBuilder { 13 | public: 14 | #ifdef __ANDROID__ 15 | WindowBuilderGl(ANativeWindow *native_window, const Vec2I &window_size); 16 | #else 17 | explicit WindowBuilderGl(const Vec2I &logical_size); 18 | #endif 19 | 20 | ~WindowBuilderGl() override; 21 | 22 | uint8_t create_window(const Vec2I &logical_size, const std::string &title) override; 23 | 24 | std::shared_ptr request_device() override; 25 | 26 | std::shared_ptr create_queue() override; 27 | 28 | private: 29 | #ifdef __ANDROID__ 30 | bool init_display(); 31 | 32 | bool init_surface(); 33 | 34 | bool init_context(); 35 | 36 | EGLDisplay egl_display_; 37 | EGLSurface egl_surface_; 38 | EGLContext egl_context_; 39 | EGLConfig egl_config_; 40 | #endif 41 | }; 42 | 43 | } // namespace Pathfinder 44 | 45 | #endif // PATHFINDER_WINDOW_BUILDER_GL_H 46 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_BUFFER_VK_H 2 | #define PATHFINDER_GPU_BUFFER_VK_H 3 | 4 | #include "../buffer.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | class DeviceVk; 10 | 11 | class BufferVk : public Buffer { 12 | friend class DeviceVk; 13 | friend class CommandEncoderVk; 14 | 15 | public: 16 | ~BufferVk() override; 17 | 18 | void upload_via_mapping(size_t data_size, size_t offset, const void* data) override; 19 | 20 | void download_via_mapping(size_t data_size, size_t offset, void* data) override; 21 | 22 | void set_label(const std::string& label) override; 23 | 24 | VkBuffer get_vk_buffer(); 25 | 26 | VkDeviceMemory get_vk_device_memory(); 27 | 28 | private: 29 | BufferVk(VkDevice vk_device, const BufferDescriptor& desc); 30 | 31 | void create_staging_buffer(DeviceVk* device_vk); 32 | 33 | VkBuffer vk_buffer_{}; 34 | VkDeviceMemory vk_device_memory_{}; 35 | 36 | VkBuffer vk_staging_buffer_{}; 37 | VkDeviceMemory vk_staging_device_memory_{}; 38 | 39 | VkDevice vk_device_{}; 40 | }; 41 | 42 | } // namespace Pathfinder 43 | 44 | #endif // PATHFINDER_GPU_BUFFER_VK_H 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pathfinder C++ 2 | 3 | This is a C++ port of [Pathfinder 3](https://github.com/servo/pathfinder) with a Vulkan backend added. 4 | 5 | ## Requirements 6 | 7 | * C++14. 8 | * D3d9 mode: `Vulkan` / `OpenGL 3.3 (or higher)` / `OpenGL ES 3.0 (or higher)` / `WebGL2`. 9 | * D3d11 mode: `Vulkan` / `OpenGL 4.3 (or higher)` / `OpenGL ES 3.1 (or higher)`. 10 | 11 | Notable: The D3d11 mode has some limits in an OpenGL ES context because, for ES, it's impossible to read & write 12 | the same image in a single compute invocation. 13 | 14 | ## Run demo 15 | 16 | ### Shader generation (Optional) 17 | 18 | * Run `src/shaders/compile_and_convert.ps1` to generate embedded shader headers. You should have Vulkan SDK installed 19 | first. 20 | 21 | ### Windows / Linux / Mac 22 | 23 | * Initialize submodules. 24 | * Build and run the CMake project `demo/native/CMakeList.txt`. 25 | 26 | ### Android 27 | 28 | * Copy `assets` into `demo/android/app/src/main`. 29 | * Open `demo/android` in Android Studio. 30 | * Build and run. 31 | 32 | ### Web 33 | 34 | * Set up emscripten environment. 35 | * Run `build_wasm.sh` to build the demo. 36 | * Run `demo/web/serve.sh` to serve a local website. 37 | * Open http://127.0.0.1:8000/. 38 | -------------------------------------------------------------------------------- /pathfinder/gpu/render_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PIPELINE_H 2 | #define PATHFINDER_GPU_RENDER_PIPELINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "base.h" 10 | 11 | namespace Pathfinder { 12 | 13 | class RenderPipeline { 14 | public: 15 | RenderPipeline(const std::vector& attribute_descriptions, 16 | BlendState blend_state, 17 | std::string label) 18 | : attribute_descriptions_(attribute_descriptions), blend_state_(blend_state), label_(std::move(label)){}; 19 | 20 | virtual ~RenderPipeline() = default; 21 | 22 | const std::vector& get_attribute_descriptions() const { 23 | return attribute_descriptions_; 24 | } 25 | 26 | BlendState get_blend_state() const { 27 | return blend_state_; 28 | } 29 | 30 | protected: 31 | std::vector attribute_descriptions_; 32 | 33 | BlendState blend_state_{}; 34 | 35 | /// Debug label. 36 | std::string label_; 37 | }; 38 | 39 | } // namespace Pathfinder 40 | 41 | #endif // PATHFINDER_GPU_RENDER_PIPELINE_H 42 | -------------------------------------------------------------------------------- /pathfinder/gpu/framebuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_FRAMEBUFFER_H 2 | #define PATHFINDER_GPU_FRAMEBUFFER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "texture.h" 8 | 9 | namespace Pathfinder { 10 | 11 | /// Creation of a framebuffer is render pass dependent. 12 | class Framebuffer { 13 | public: 14 | virtual ~Framebuffer() = default; 15 | 16 | std::shared_ptr get_texture() const { 17 | return texture_; 18 | } 19 | 20 | Vec2I get_size() const { 21 | if (texture_) { 22 | return texture_->get_size(); 23 | } 24 | return {}; 25 | } 26 | 27 | // Sometimes, we need to update label for a framebuffer as we reuse it for another purpose. 28 | virtual void set_label(const std::string& label) { 29 | label_ = label; 30 | } 31 | 32 | protected: 33 | /// Render to screen or swap chain. 34 | Framebuffer(){} 35 | 36 | /// Render to a texture. 37 | explicit Framebuffer(const std::shared_ptr& texture) : texture_(texture) {} 38 | 39 | std::shared_ptr texture_; 40 | 41 | /// Debug label. 42 | std::string label_; 43 | }; 44 | 45 | } // namespace Pathfinder 46 | 47 | #endif // PATHFINDER_GPU_FRAMEBUFFER_H 48 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_QUEUE_GL_H 2 | #define PATHFINDER_GPU_QUEUE_GL_H 3 | 4 | #include 5 | 6 | #include "../queue.h" 7 | #include "fence.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class QueueGl : public Queue { 12 | friend class WindowGl; 13 | 14 | public: 15 | void submit(const std::shared_ptr &encoder, const std::shared_ptr &fence) override { 16 | if (encoder->submitted_) { 17 | Logger::error("Attempted to submit an encoder that's already been submitted!"); 18 | return; 19 | } 20 | 21 | encoder->submitted_ = true; 22 | 23 | encoder->finish(); 24 | 25 | if (fence) { 26 | auto fence_gl = (FenceGl *)fence.get(); 27 | fence_gl->wait(); 28 | } 29 | } 30 | 31 | void submit_and_wait(const std::shared_ptr &encoder) override { 32 | if (encoder->submitted_) { 33 | Logger::error("Attempted to submit an encoder that's already been submitted!"); 34 | return; 35 | } 36 | 37 | encoder->submitted_ = true; 38 | 39 | encoder->finish(); 40 | } 41 | }; 42 | 43 | } // namespace Pathfinder 44 | 45 | #endif // PATHFINDER_GPU_QUEUE_GL_H 46 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/tiler.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D9_TILER_H 2 | #define PATHFINDER_D3D9_TILER_H 3 | 4 | #include "../data/data.h" 5 | #include "../data/path.h" 6 | #include "object_builder.h" 7 | 8 | namespace Pathfinder { 9 | 10 | /// This might be the most important class for building on D3D9 level. 11 | /// One tiler for one outline. 12 | struct Tiler { 13 | public: 14 | Tiler(SceneBuilderD3D9& _scene_builder, 15 | uint32_t path_id, 16 | Outline _outline, 17 | FillRule fill_rule, 18 | const RectF& view_box, 19 | const std::shared_ptr& clip_path_id, 20 | const std::vector& built_clip_paths, 21 | TilingPathInfo path_info); 22 | 23 | ObjectBuilder object_builder; 24 | 25 | /// Generate fills and tiles. 26 | void generate_tiles(); 27 | 28 | private: 29 | SceneBuilderD3D9& scene_builder; 30 | 31 | Outline outline; 32 | 33 | std::shared_ptr clip_path; // Optional 34 | 35 | /// Process all paths of the attached shape. 36 | void generate_fills(); 37 | 38 | /// Prepare the winding (backdrops) vector for solid tiles. 39 | void prepare_tiles(); 40 | }; 41 | 42 | } // namespace Pathfinder 43 | 44 | #endif // PATHFINDER_D3D9_TILER_H 45 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | 2 | if (NOT EXISTS "@GLFW_BINARY_DIR@/install_manifest.txt") 3 | message(FATAL_ERROR "Cannot find install manifest: \"@GLFW_BINARY_DIR@/install_manifest.txt\"") 4 | endif() 5 | 6 | file(READ "@GLFW_BINARY_DIR@/install_manifest.txt" files) 7 | string(REGEX REPLACE "\n" ";" files "${files}") 8 | 9 | foreach (file ${files}) 10 | message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") 11 | if (EXISTS "$ENV{DESTDIR}${file}") 12 | exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 13 | OUTPUT_VARIABLE rm_out 14 | RETURN_VALUE rm_retval) 15 | if (NOT "${rm_retval}" STREQUAL 0) 16 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") 17 | endif() 18 | elseif (IS_SYMLINK "$ENV{DESTDIR}${file}") 19 | EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 20 | OUTPUT_VARIABLE rm_out 21 | RETURN_VALUE rm_retval) 22 | if (NOT "${rm_retval}" STREQUAL 0) 23 | message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"") 24 | endif() 25 | else() 26 | message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") 27 | endif() 28 | endforeach() 29 | 30 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d9/tile_clip_combine.frag: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | // pathfinder/shaders/tile_clip_combine.fs.glsl 4 | // 5 | // Copyright © 2020 The Pathfinder Project Developers. 6 | // 7 | // Licensed under the Apache License, Version 2.0 or the MIT license 9 | // , at your 10 | // option. This file may not be copied, modified, or distributed 11 | // except according to those terms. 12 | 13 | precision highp float; 14 | 15 | #ifdef GL_ES 16 | precision highp sampler2D; 17 | #endif 18 | 19 | #ifdef VULKAN 20 | layout(binding = 1) uniform sampler2D uSrc; 21 | 22 | layout(location = 0) in vec2 vTexCoord0; 23 | layout(location = 1) in float vBackdrop0; 24 | layout(location = 2) in vec2 vTexCoord1; 25 | layout(location = 3) in float vBackdrop1; 26 | 27 | layout(location = 0) out vec4 oFragColor; 28 | #else 29 | uniform sampler2D uSrc; 30 | 31 | in vec2 vTexCoord0; 32 | in float vBackdrop0; 33 | in vec2 vTexCoord1; 34 | in float vBackdrop1; 35 | 36 | out vec4 oFragColor; 37 | #endif 38 | 39 | void main() { 40 | oFragColor = min(abs(texture(uSrc, vTexCoord0) + vBackdrop0), 41 | abs(texture(uSrc, vTexCoord1) + vBackdrop1)); 42 | } 43 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/window.cpp: -------------------------------------------------------------------------------- 1 | #include "window.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../../common/logger.h" 7 | #include "swap_chain.h" 8 | 9 | namespace Pathfinder { 10 | 11 | #ifndef __ANDROID__ 12 | WindowGl::WindowGl(const Vec2I &size, GLFWwindow *window_handle) : Window(size, window_handle) {} 13 | #else 14 | WindowGl::WindowGl(const Vec2I &size, EGLDisplay egl_display, EGLSurface egl_surface, EGLContext egl_context) 15 | : Window(size) { 16 | egl_display_ = egl_display; 17 | egl_surface_ = egl_surface; 18 | egl_context_ = egl_context; 19 | } 20 | #endif 21 | 22 | std::shared_ptr WindowGl::get_swap_chain(const std::shared_ptr &device) { 23 | if (swapchain_) { 24 | return swapchain_; 25 | } 26 | 27 | #ifndef __ANDROID__ 28 | swapchain_ = std::make_shared(get_physical_size(), glfw_window_); 29 | #else 30 | swapchain_ = std::make_shared(get_physical_size(), egl_display_, egl_surface_, egl_context_); 31 | #endif 32 | 33 | return swapchain_; 34 | } 35 | 36 | void WindowGl::destroy() { 37 | #ifndef __ANDROID__ 38 | if (glfw_window_) { 39 | glfwDestroyWindow(glfw_window_); 40 | glfw_window_ = nullptr; 41 | } 42 | #endif 43 | } 44 | 45 | } // namespace Pathfinder 46 | -------------------------------------------------------------------------------- /pathfinder/gpu/swap_chain.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_SWAP_CHAIN_H 2 | #define PATHFINDER_GPU_SWAP_CHAIN_H 3 | 4 | #include "../common/math/vec2.h" 5 | #include "command_encoder.h" 6 | #include "framebuffer.h" 7 | #include "render_pass.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class SwapChain { 12 | public: 13 | explicit SwapChain(Vec2I size) : size_(size) {} 14 | 15 | virtual ~SwapChain() = default; 16 | 17 | /// Swap chain framebuffer size. 18 | Vec2I size_; 19 | 20 | /** 21 | * Get a swap chain render pass. 22 | * @return Render pass 23 | */ 24 | virtual std::shared_ptr get_render_pass() = 0; 25 | 26 | /** 27 | * Get current texture. 28 | * @return Texture 29 | */ 30 | virtual std::shared_ptr get_surface_texture() = 0; 31 | 32 | virtual TextureFormat get_surface_format() const = 0; 33 | 34 | /// Acquire current texture in the swap chain. 35 | virtual bool acquire_image() = 0; 36 | 37 | virtual void submit(const std::shared_ptr &encoder) = 0; 38 | 39 | /** 40 | * Flush command buffers to the current image. 41 | */ 42 | virtual void present() = 0; 43 | 44 | /// Clean up swap chain resources. 45 | virtual void destroy() = 0; 46 | }; 47 | 48 | } // namespace Pathfinder 49 | 50 | #endif // PATHFINDER_GPU_SWAP_CHAIN_H 51 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/render_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PIPELINE_GL_H 2 | #define PATHFINDER_GPU_RENDER_PIPELINE_GL_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../render_pipeline.h" 8 | #include "debug_marker.h" 9 | #include "program.h" 10 | 11 | namespace Pathfinder { 12 | 13 | class RenderPipelineGl : public RenderPipeline { 14 | friend class DeviceGl; 15 | 16 | public: 17 | std::shared_ptr get_program() { 18 | return program_; 19 | } 20 | 21 | private: 22 | RenderPipelineGl(const std::shared_ptr &vert_shader_module, 23 | const std::shared_ptr &frag_shader_module, 24 | const std::vector &attribute_descriptions, 25 | BlendState blend_state, 26 | std::string label) 27 | : RenderPipeline(attribute_descriptions, blend_state, std::move(label)) { 28 | program_ = std::make_shared(vert_shader_module, frag_shader_module); 29 | 30 | gl_check_error("create_render_pipeline"); 31 | 32 | DebugMarker::label_program(program_->get_handle(), label_ + " program"); 33 | } 34 | 35 | std::shared_ptr program_; 36 | }; 37 | 38 | } // namespace Pathfinder 39 | 40 | #endif // PATHFINDER_GPU_RENDER_PIPELINE_GL_H 41 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/compute_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_COMPUTE_PIPELINE_VK_H 2 | #define PATHFINDER_GPU_COMPUTE_PIPELINE_VK_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../compute_pipeline.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class ComputePipelineVk : public ComputePipeline { 12 | friend class DeviceVk; 13 | 14 | public: 15 | ~ComputePipelineVk() override { 16 | vkDestroyDescriptorSetLayout(vk_device_, vk_descriptor_set_layout_, nullptr); 17 | vkDestroyPipeline(vk_device_, vk_pipeline_, nullptr); 18 | vkDestroyPipelineLayout(vk_device_, vk_layout_, nullptr); 19 | } 20 | 21 | VkPipeline get_pipeline() const { 22 | return vk_pipeline_; 23 | } 24 | 25 | VkPipelineLayout get_layout() const { 26 | return vk_layout_; 27 | } 28 | 29 | VkDescriptorSetLayout get_descriptor_set_layout() const { 30 | return vk_descriptor_set_layout_; 31 | } 32 | 33 | private: 34 | ComputePipelineVk(VkDevice vk_device, std::string label) : vk_device_(vk_device) { 35 | label_ = std::move(label); 36 | } 37 | 38 | VkPipeline vk_pipeline_{}; 39 | 40 | VkDescriptorSetLayout vk_descriptor_set_layout_{}; 41 | 42 | VkPipelineLayout vk_layout_{}; 43 | 44 | VkDevice vk_device_{}; 45 | }; 46 | 47 | } // namespace Pathfinder 48 | 49 | #endif // PATHFINDER_GPU_COMPUTE_PIPELINE_VK_H 50 | -------------------------------------------------------------------------------- /pathfinder/core/path2d.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_PATH2D_H 2 | #define PATHFINDER_PATH2D_H 3 | 4 | #include "../common/math/rect.h" 5 | #include "../common/math/vec2.h" 6 | #include "data/path.h" 7 | 8 | namespace Pathfinder { 9 | 10 | class Path2d { 11 | public: 12 | // Basic geometries. 13 | // ----------------------------------------------- 14 | void close_path(); 15 | 16 | void move_to(float x, float y); 17 | 18 | void line_to(float x, float y); 19 | 20 | void quadratic_to(float cx, float cy, float x, float y); 21 | 22 | void cubic_to(float cx, float cy, float cx1, float cy1, float x, float y); 23 | // ----------------------------------------------- 24 | 25 | // Advanced geometries. 26 | // ----------------------------------------------- 27 | void add_line(const Vec2F &start, const Vec2F &end); 28 | 29 | void add_rect(const RectF &rect, float corner_radius = 0); 30 | 31 | void add_rect_with_corners(const RectF &rect, const RectF &corner_radius); 32 | 33 | void add_circle(const Vec2F ¢er, float radius); 34 | // ----------------------------------------------- 35 | 36 | /// Returns the outline. 37 | Outline into_outline(); 38 | 39 | private: 40 | Contour current_contour; 41 | 42 | Outline outline; 43 | 44 | void flush_current_contour(); 45 | }; 46 | 47 | } // namespace Pathfinder 48 | 49 | #endif // PATHFINDER_PATH2D_H 50 | -------------------------------------------------------------------------------- /third_party/glfw/src/xkb_unicode.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Linux - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2014 Jonas Ådahl 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | #define GLFW_INVALID_CODEPOINT 0xffffffffu 28 | 29 | uint32_t _glfwKeySym2Unicode(unsigned int keysym); 30 | 31 | -------------------------------------------------------------------------------- /demo/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 36 5 | ndkVersion "23.1.7779620" 6 | 7 | defaultConfig { 8 | applicationId "graphics.pathfinder.demo" 9 | minSdkVersion 24 10 | targetSdkVersion 36 11 | 12 | // Shader compilation directives, put glsl shaders to app/src/main/shaders. 13 | // Android Studio will pick them up and compile them into APK/assets/shaders. 14 | // KNOWN ISSUE: if shaders having errors, it takes long time for gradle to timeout. 15 | // But it will eventually time out and complain about shader compiling. 16 | shaders { 17 | glslcArgs.addAll(['-c', '-g']) 18 | } 19 | externalNativeBuild { 20 | cmake { 21 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' 22 | arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static', "-DCMAKE_BUILD_TYPE=Release" 23 | } 24 | } 25 | } 26 | externalNativeBuild { 27 | cmake { 28 | version '3.18.1' 29 | path 'src/main/cpp/CMakeLists.txt' 30 | } 31 | } 32 | buildTypes.release.minifyEnabled = false 33 | buildFeatures.prefab = true 34 | namespace 'graphics.pathfinder.demo' 35 | } 36 | 37 | dependencies { 38 | implementation 'androidx.appcompat:appcompat:1.6.1' 39 | implementation 'androidx.games:games-activity:1.2.1' 40 | } 41 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${MACOSX_BUNDLE_EXECUTABLE_NAME} 9 | CFBundleGetInfoString 10 | ${MACOSX_BUNDLE_INFO_STRING} 11 | CFBundleIconFile 12 | ${MACOSX_BUNDLE_ICON_FILE} 13 | CFBundleIdentifier 14 | ${MACOSX_BUNDLE_GUI_IDENTIFIER} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleLongVersionString 18 | ${MACOSX_BUNDLE_LONG_VERSION_STRING} 19 | CFBundleName 20 | ${MACOSX_BUNDLE_BUNDLE_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | ${MACOSX_BUNDLE_SHORT_VERSION_STRING} 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | ${MACOSX_BUNDLE_BUNDLE_VERSION} 29 | CSResourcesFileMapped 30 | 31 | LSRequiresCarbon 32 | 33 | NSHumanReadableCopyright 34 | ${MACOSX_BUNDLE_COPYRIGHT} 35 | NSHighResolutionCapable 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /pathfinder/core/d3d9/object_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D9_OBJECT_BUILDER_H 2 | #define PATHFINDER_D3D9_OBJECT_BUILDER_H 3 | 4 | #include 5 | 6 | #include "../data/built_path.h" 7 | #include "data/gpu_data.h" 8 | #include "scene_builder.h" 9 | 10 | namespace Pathfinder { 11 | 12 | class ObjectBuilder { 13 | public: 14 | BuiltPath built_path; 15 | std::vector fills; 16 | RectF bounds; 17 | 18 | ObjectBuilder() = default; 19 | 20 | ObjectBuilder(uint32_t path_id, 21 | RectF path_bounds, 22 | const RectF &view_box_bounds, 23 | FillRule fill_rule, 24 | const std::shared_ptr &clip_path_id, 25 | const TilingPathInfo &path_info); 26 | 27 | /// Alpha tile id is set at this stage. 28 | void add_fill(SceneBuilderD3D9 &scene_builder, const LineSegmentF &segment_, Vec2I tile_coords); 29 | 30 | void adjust_alpha_tile_backdrop(const Vec2I &tile_coords, int8_t delta); 31 | 32 | int tile_coords_to_local_index_unchecked(const Vec2I &coords) const; 33 | 34 | /** 35 | * Get the alpha tile by tile coordinates, and allocate one if there's none. 36 | * @param scene_builder 37 | * @param tile_coords 38 | * @return Alpha tile ID. 39 | */ 40 | AlphaTileId get_or_allocate_alpha_tile_index(SceneBuilderD3D9 &scene_builder, const Vec2I &tile_coords); 41 | }; 42 | 43 | } // namespace Pathfinder 44 | 45 | #endif // PATHFINDER_D3D9_OBJECT_BUILDER_H 46 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d9/tile_clip_copy.vert: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | // pathfinder/shaders/tile_clip_copy.vs.glsl 4 | // 5 | // Copyright © 2020 The Pathfinder Project Developers. 6 | // 7 | // Licensed under the Apache License, Version 2.0 or the MIT license 9 | // , at your 10 | // option. This file may not be copied, modified, or distributed 11 | // except according to those terms. 12 | 13 | precision highp float; 14 | 15 | #ifdef GL_ES 16 | precision highp sampler2D; 17 | #endif 18 | 19 | #ifdef VULKAN 20 | layout(binding = 0) uniform bUniform { 21 | #else 22 | layout(std140) uniform bUniform { 23 | #endif 24 | vec2 uTileSize; // Fixed as (16, 16). 25 | vec2 uFramebufferSize; // Mask framebuffer. Dynamic as (4096, 1024 * page_count). 26 | }; 27 | 28 | #ifdef VULKAN 29 | layout(location = 0) in uvec2 aTileOffset; 30 | layout(location = 1) in int aTileIndex; 31 | 32 | layout(location = 0) out vec2 vTexCoord; 33 | #else 34 | in uvec2 aTileOffset; 35 | in int aTileIndex; 36 | 37 | out vec2 vTexCoord; 38 | #endif 39 | 40 | void main() { 41 | vec2 position = vec2(ivec2(aTileIndex % 256, aTileIndex / 256) + ivec2(aTileOffset)); 42 | position *= vec2(16.0, 4.0) / uFramebufferSize; 43 | 44 | vTexCoord = position; 45 | 46 | if (aTileIndex < 0) { 47 | position = vec2(0.0); 48 | } 49 | 50 | gl_Position = vec4(mix(vec2(-1.0), vec2(1.0), position), 0.0, 1.0); 51 | } 52 | -------------------------------------------------------------------------------- /demo/android/app/src/main/cpp/AndroidMain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "native_engine.h" 4 | 5 | NativeEngine *native_engine = nullptr; 6 | 7 | // Process the next main command. 8 | void handle_cmd(android_app *app, int32_t cmd) { 9 | switch (cmd) { 10 | case APP_CMD_INIT_WINDOW: 11 | // The window is being shown, get it ready. 12 | native_engine = new NativeEngine(app); 13 | native_engine->init_app(false); 14 | break; 15 | case APP_CMD_TERM_WINDOW: 16 | // The window is being hidden or closed, clean it up. 17 | delete native_engine; 18 | break; 19 | default: 20 | __android_log_print(ANDROID_LOG_INFO, "Pathfinder", "Event not handled: %d", cmd); 21 | } 22 | } 23 | 24 | void android_main(struct android_app *app) { 25 | // Set the callback to process system events. 26 | app->onAppCmd = handle_cmd; 27 | 28 | // Used to poll the events in the main loop. 29 | int events; 30 | android_poll_source *source; 31 | 32 | // Main loop. 33 | do { 34 | if (ALooper_pollOnce(0, nullptr, &events, (void **)&source) >= 0) { 35 | if (source != nullptr) { 36 | source->process(app, source); 37 | } 38 | } 39 | 40 | // Render if the engine is ready. 41 | if (native_engine && native_engine->is_ready()) { 42 | native_engine->draw_frame(); 43 | } 44 | } while (app->destroyRequested == 0); 45 | } 46 | -------------------------------------------------------------------------------- /third_party/glfw/src/cocoa_time.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 macOS - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2009-2021 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | #define GLFW_COCOA_LIBRARY_TIMER_STATE _GLFWtimerNS ns; 28 | 29 | // Cocoa-specific global timer data 30 | // 31 | typedef struct _GLFWtimerNS 32 | { 33 | uint64_t frequency; 34 | } _GLFWtimerNS; 35 | 36 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/framebuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "framebuffer.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "../framebuffer.h" 7 | #include "debug_marker.h" 8 | 9 | namespace Pathfinder { 10 | 11 | FramebufferGl::FramebufferGl() { 12 | gl_framebuffer_ = 0; 13 | label_ = "screen framebuffer"; 14 | } 15 | 16 | FramebufferGl::FramebufferGl(const std::shared_ptr &texture) : Framebuffer(texture) { 17 | auto texture_gl = static_cast(texture.get()); 18 | 19 | // Set up framebuffer. 20 | glGenFramebuffers(1, &gl_framebuffer_); 21 | glBindFramebuffer(GL_FRAMEBUFFER, gl_framebuffer_); 22 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_gl->get_texture_id(), 0); 23 | 24 | // Check whether the framebuffer is OK. 25 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 26 | Logger::error("Framebuffer is not OK!"); 27 | } 28 | 29 | gl_check_error("create_framebuffer"); 30 | } 31 | 32 | FramebufferGl::~FramebufferGl() { 33 | if (gl_framebuffer_ != 0) { 34 | glDeleteFramebuffers(1, &gl_framebuffer_); 35 | } 36 | } 37 | 38 | uint32_t FramebufferGl::get_gl_handle() const { 39 | return gl_framebuffer_; 40 | } 41 | 42 | void FramebufferGl::set_label(const std::string &label) { 43 | if (gl_framebuffer_ == 0) { 44 | return; 45 | } 46 | 47 | Framebuffer::set_label(label); 48 | DebugMarker::label_framebuffer(gl_framebuffer_, label_); 49 | } 50 | 51 | } // namespace Pathfinder 52 | -------------------------------------------------------------------------------- /pathfinder/gpu/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_BUFFER_H 2 | #define PATHFINDER_GPU_BUFFER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "base.h" 8 | 9 | namespace Pathfinder { 10 | 11 | // Maximum binding number of vertex buffers for a draw call. 12 | const uint32_t MAX_VERTEX_BUFFER_BINDINGS = 8; 13 | 14 | struct BufferDescriptor { 15 | BufferType type; 16 | size_t size; 17 | MemoryProperty property; 18 | 19 | bool operator==(const BufferDescriptor& b) const { 20 | return size == b.size && type == b.type && property == b.property; 21 | } 22 | }; 23 | 24 | class Buffer { 25 | public: 26 | explicit Buffer(const BufferDescriptor& desc) : desc_(desc) {} 27 | 28 | virtual ~Buffer() = default; 29 | 30 | size_t get_size() const { 31 | return desc_.size; 32 | } 33 | 34 | BufferType get_type() const { 35 | return desc_.type; 36 | } 37 | 38 | MemoryProperty get_memory_property() const { 39 | return desc_.property; 40 | } 41 | 42 | virtual void upload_via_mapping(size_t data_size, size_t offset, const void* data) = 0; 43 | 44 | virtual void download_via_mapping(size_t data_size, size_t offset, void* data) = 0; 45 | 46 | // Sometimes, we need to update label for a buffer as we reuse it for another purpose. 47 | virtual void set_label(const std::string& label) { 48 | label_ = label; 49 | } 50 | 51 | protected: 52 | BufferDescriptor desc_; 53 | 54 | std::string label_; 55 | }; 56 | 57 | } // namespace Pathfinder 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /third_party/glfw/src/null_joystick.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2006-2017 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | GLFWbool _glfwInitJoysticksNull(void); 28 | void _glfwTerminateJoysticksNull(void); 29 | GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode); 30 | const char* _glfwGetMappingNameNull(void); 31 | void _glfwUpdateGamepadGUIDNull(char* guid); 32 | 33 | -------------------------------------------------------------------------------- /pathfinder/common/timestamp.cpp: -------------------------------------------------------------------------------- 1 | #include "timestamp.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "global_macros.h" 9 | #include "logger.h" 10 | 11 | namespace Pathfinder { 12 | 13 | Timestamp::Timestamp(const std::string &logger_tag) { 14 | logger_tag_ = logger_tag; 15 | start_time = std::chrono::steady_clock::now(); 16 | } 17 | 18 | void Timestamp::record(const std::string &label) { 19 | if (!enabled_) { 20 | return; 21 | } 22 | 23 | std::chrono::time_point current_time = std::chrono::steady_clock::now(); 24 | 25 | std::chrono::duration elapsed_time = current_time - start_time; 26 | 27 | auto elapsed_time_in_ms = round(elapsed_time.count() * 100000.0f) * 0.01f; 28 | 29 | records.push_back(elapsed_time_in_ms); 30 | labels.push_back(label); 31 | 32 | start_time = std::chrono::steady_clock::now(); 33 | } 34 | 35 | void Timestamp::reset() { 36 | records.clear(); 37 | labels.clear(); 38 | start_time = std::chrono::steady_clock::now(); 39 | } 40 | 41 | void Timestamp::print() const { 42 | if (!enabled_) { 43 | return; 44 | } 45 | 46 | for (int i = 0; i < records.size(); i++) { 47 | std::ostringstream string_stream; 48 | string_stream << i << " " << labels[i] << " " << records[i] << " ms"; 49 | Logger::info(string_stream.str(), logger_tag_); 50 | } 51 | } 52 | 53 | void Timestamp::set_enabled(bool enabled) { 54 | enabled_ = enabled; 55 | } 56 | 57 | } // namespace Pathfinder 58 | -------------------------------------------------------------------------------- /third_party/glfw/src/posix_poll.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 POSIX - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2022 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | // It is fine to use C99 in this file because it will not be built with VS 27 | //======================================================================== 28 | 29 | #include 30 | 31 | GLFWbool _glfwPollPOSIX(struct pollfd* fds, nfds_t count, double* timeout); 32 | 33 | -------------------------------------------------------------------------------- /pathfinder/shaders/convert_files_to_header.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import struct 4 | 5 | target_extension = sys.argv[1] 6 | 7 | for current_dir, dir_list, file_list in os.walk(r"./"): 8 | for file_name in file_list: 9 | if not file_name.endswith("." + target_extension): 10 | continue 11 | 12 | base_name = os.path.splitext(file_name)[0] 13 | base_name = base_name.replace(".", "_") 14 | base_name = base_name.replace("-", "_") 15 | base_name += "_" + target_extension 16 | 17 | header_file_name = base_name + ".h" 18 | 19 | dst_stream = open(current_dir + "/" + header_file_name, 'w') 20 | dst_stream.write("#ifndef PATHFINDER_RESOURCE_" + base_name.upper() + "_H\n") 21 | dst_stream.write("#define PATHFINDER_RESOURCE_" + base_name.upper() + "_H\n\n") 22 | 23 | dst_stream.write("namespace Pathfinder {\n static uint8_t " + base_name + "[] = {") 24 | 25 | with open(current_dir + "/" + file_name, 'rb') as src_stream: 26 | file_text = src_stream.read() 27 | char = struct.unpack(' 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | 28 | #include 29 | 30 | #define GLFW_WIN32_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32; 31 | 32 | // Win32-specific global timer data 33 | // 34 | typedef struct _GLFWtimerWin32 35 | { 36 | uint64_t frequency; 37 | } _GLFWtimerWin32; 38 | 39 | -------------------------------------------------------------------------------- /third_party/glfw/src/posix_time.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 POSIX - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2002-2006 Marcus Geelnard 5 | // Copyright (c) 2006-2017 Camilla Löwy 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | 28 | #define GLFW_POSIX_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix; 29 | 30 | #include 31 | #include 32 | 33 | 34 | // POSIX-specific global timer data 35 | // 36 | typedef struct _GLFWtimerPOSIX 37 | { 38 | clockid_t clock; 39 | uint64_t frequency; 40 | } _GLFWtimerPOSIX; 41 | 42 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/render_pipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_RENDER_PIPELINE_VK_H 2 | #define PATHFINDER_GPU_RENDER_PIPELINE_VK_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../render_pipeline.h" 8 | 9 | namespace Pathfinder { 10 | 11 | class RenderPipelineVk : public RenderPipeline { 12 | friend class DeviceVk; 13 | 14 | public: 15 | ~RenderPipelineVk() override { 16 | vkDestroyDescriptorSetLayout(vk_device_, vk_descriptor_set_layout_, nullptr); 17 | vkDestroyPipeline(vk_device_, vk_pipeline_, nullptr); 18 | vkDestroyPipelineLayout(vk_device_, vk_layout_, nullptr); 19 | } 20 | 21 | VkPipeline get_pipeline() const { 22 | return vk_pipeline_; 23 | } 24 | 25 | VkPipelineLayout get_layout() const { 26 | return vk_layout_; 27 | } 28 | 29 | VkDescriptorSetLayout get_descriptor_set_layout() const { 30 | return vk_descriptor_set_layout_; 31 | } 32 | 33 | private: 34 | RenderPipelineVk(VkDevice vk_device, 35 | const std::vector &attribute_descriptions, 36 | BlendState blend_state, 37 | std::string label) 38 | : RenderPipeline(attribute_descriptions, blend_state, std::move(label)), vk_device_(vk_device) {} 39 | 40 | // A walkaround of pass denpendency. 41 | std::shared_ptr render_pass_vk_; 42 | 43 | VkPipeline vk_pipeline_{}; 44 | 45 | VkDescriptorSetLayout vk_descriptor_set_layout_{}; 46 | 47 | VkPipelineLayout vk_layout_{}; 48 | 49 | VkDevice vk_device_{}; 50 | }; 51 | 52 | } // namespace Pathfinder 53 | 54 | #endif // PATHFINDER_GPU_RENDER_PIPELINE_VK_H 55 | -------------------------------------------------------------------------------- /pathfinder/common/global_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GLOBAL_MACROS_H 2 | #define PATHFINDER_GLOBAL_MACROS_H 3 | 4 | /// Platform marcos. 5 | #ifdef __EMSCRIPTEN__ 6 | #define PATHFINDER_EMSCRIPTEN 7 | #elif defined(_WIN32) 8 | #define PATHFINDER_WINDOWS 9 | #elif defined(__linux__) && !defined(__ANDROID__) 10 | #define PATHFINDER_LINUX 11 | #elif defined(__ANDROID__) 12 | #define PATHFINDER_ANDROID 13 | #elif defined(__APPLE__) 14 | #define PATHFINDER_APPLE 15 | 16 | #import 17 | #if TARGET_OS_OSX 18 | #define PATHFINDER_MACOS 19 | #elif TARGET_OS_IPHONE 20 | #define PATHFINDER_IOS 21 | #endif 22 | #endif 23 | 24 | // Enable D3d11 render level. 25 | #define PATHFINDER_ENABLE_D3D11 26 | 27 | // D3d11 level is not available in Web. 28 | #ifdef PATHFINDER_EMSCRIPTEN 29 | #undef PATHFINDER_ENABLE_D3D11 30 | #endif 31 | 32 | // Enable this if ES3.0 support is needed. 33 | // #define PATHFINDER_MINIMUM_SHADER_VERSION_SUPPORT 34 | 35 | // WebGL only supports ES3.0 shaders. 36 | #if defined(PATHFINDER_EMSCRIPTEN) || defined(PATHFINDER_ANDROID) 37 | #define PATHFINDER_MINIMUM_SHADER_VERSION_SUPPORT 38 | #endif 39 | 40 | // Enable DEBUG mode. Influencing performance. 41 | // For the GL backend, error checking is enabled. 42 | // For Vulkan , the validation layers are enabled. 43 | #ifndef NDEBUG 44 | #define PATHFINDER_DEBUG 45 | #endif 46 | 47 | /// Enable building scenes (on D3d9 level) in parallel. 48 | #define PATHFINDER_THREADS 4 49 | 50 | /// Enable SIMD. 51 | #if !defined(PATHFINDER_EMSCRIPTEN) && !defined(PATHFINDER_APPLE) 52 | #define PATHFINDER_ENABLE_SIMD 53 | #endif 54 | 55 | #endif // PATHFINDER_GLOBAL_MACROS_H 56 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/blit_frag_spv.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_BLIT_FRAG_SPV_H 2 | #define PATHFINDER_RESOURCE_BLIT_FRAG_SPV_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t blit_frag_spv[] = {3,2,35,7,0,0,1,0,11,0,13,0,20,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,7,0,4,0,0,0,4,0,0,0,109,97,105,110,0,0,0,0,9,0,0,0,17,0,0,0,16,0,3,0,4,0,0,0,7,0,0,0,3,0,3,0,1,0,0,0,54,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5,0,5,0,9,0,0,0,111,70,114,97,103,67,111,108,111,114,0,0,5,0,5,0,13,0,0,0,117,84,101,120,116,117,114,101,0,0,0,0,5,0,3,0,17,0,0,0,118,85,86,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,17,0,0,0,30,0,0,0,0,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,25,0,9,0,10,0,0,0,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,11,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,11,0,0,0,59,0,4,0,12,0,0,0,13,0,0,0,0,0,0,0,23,0,4,0,15,0,0,0,6,0,0,0,2,0,0,0,32,0,4,0,16,0,0,0,1,0,0,0,15,0,0,0,59,0,4,0,16,0,0,0,17,0,0,0,1,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,61,0,4,0,11,0,0,0,14,0,0,0,13,0,0,0,61,0,4,0,15,0,0,0,18,0,0,0,17,0,0,0,87,0,5,0,7,0,0,0,19,0,0,0,14,0,0,0,18,0,0,0,62,0,3,0,9,0,0,0,19,0,0,0,253,0,1,0,56,0,1,0}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_BLIT_FRAG_SPV_H 9 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/tile_clip_copy_frag_spv.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_TILE_CLIP_COPY_FRAG_SPV_H 2 | #define PATHFINDER_RESOURCE_TILE_CLIP_COPY_FRAG_SPV_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t tile_clip_copy_frag_spv[] = {3,2,35,7,0,0,1,0,11,0,13,0,20,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,7,0,4,0,0,0,4,0,0,0,109,97,105,110,0,0,0,0,9,0,0,0,17,0,0,0,16,0,3,0,4,0,0,0,7,0,0,0,3,0,3,0,1,0,0,0,54,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5,0,5,0,9,0,0,0,111,70,114,97,103,67,111,108,111,114,0,0,5,0,4,0,13,0,0,0,117,83,114,99,0,0,0,0,5,0,5,0,17,0,0,0,118,84,101,120,67,111,111,114,100,0,0,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,33,0,0,0,1,0,0,0,71,0,4,0,17,0,0,0,30,0,0,0,0,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,25,0,9,0,10,0,0,0,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,11,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,11,0,0,0,59,0,4,0,12,0,0,0,13,0,0,0,0,0,0,0,23,0,4,0,15,0,0,0,6,0,0,0,2,0,0,0,32,0,4,0,16,0,0,0,1,0,0,0,15,0,0,0,59,0,4,0,16,0,0,0,17,0,0,0,1,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,61,0,4,0,11,0,0,0,14,0,0,0,13,0,0,0,61,0,4,0,15,0,0,0,18,0,0,0,17,0,0,0,87,0,5,0,7,0,0,0,19,0,0,0,14,0,0,0,18,0,0,0,62,0,3,0,9,0,0,0,19,0,0,0,253,0,1,0,56,0,1,0}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_TILE_CLIP_COPY_FRAG_SPV_H 9 | -------------------------------------------------------------------------------- /demo/android/app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | project(pathfinder_android_demo) 4 | 5 | # Integrate GameActivity, refer to 6 | # https://d.android.com/games/agdk/integrate-game-activity 7 | # for the detailed instructions. 8 | find_package(game-activity REQUIRED CONFIG) 9 | 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -frtti -Wall \ 11 | -DVK_USE_PLATFORM_ANDROID_KHR") 12 | 13 | include_directories(../../../../../../) 14 | include_directories(../../../../../../third_party) 15 | include_directories(../../../../../../demo/common) 16 | 17 | # Set some flags before adding. 18 | set(PATHFINDER_BUILD_DEMO ON CACHE BOOL "" FORCE) 19 | set(PATHFINDER_BACKEND_VULKAN ON CACHE BOOL "" FORCE) 20 | add_subdirectory(../../../../../../ pathfinder) 21 | 22 | 23 | ################### GL 24 | if (${ANDROID_PLATFORM_LEVEL} LESS 12) 25 | message(FATAL_ERROR "OpenGL 2 is not supported before API level 11 \ 26 | (currently using ${ANDROID_PLATFORM_LEVEL}).") 27 | return() 28 | elseif (${ANDROID_PLATFORM_LEVEL} LESS 18) 29 | add_definitions("-DDYNAMIC_ES3") 30 | set(GL3STUB_SRC gl3stub.c) 31 | set(OPENGL_LIB GLESv2) 32 | else () 33 | set(OPENGL_LIB GLESv3) 34 | endif () 35 | ################### GL 36 | 37 | link_directories(lib/${ANDROID_ABI}) 38 | 39 | add_library(${CMAKE_PROJECT_NAME} SHARED 40 | AndroidMain.cpp 41 | vulkan_wrapper.cpp 42 | GameActivitySources.cpp 43 | native_engine.cpp) 44 | 45 | target_link_libraries(${CMAKE_PROJECT_NAME} 46 | game-activity::game-activity 47 | log 48 | android 49 | pathfinder 50 | pathfinder_demo_common 51 | EGL # GL 52 | ${OPENGL_LIB} # GL 53 | ) 54 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/texture.cpp: -------------------------------------------------------------------------------- 1 | #include "texture.h" 2 | 3 | #include "../../common/global_macros.h" 4 | #include "debug_marker.h" 5 | 6 | namespace Pathfinder { 7 | 8 | TextureGl::TextureGl(const TextureDescriptor& desc) : Texture(desc) { 9 | // Generate a texture. 10 | glGenTextures(1, &gl_id_); 11 | glBindTexture(GL_TEXTURE_2D, gl_id_); 12 | 13 | // Allocate space. 14 | // We need to use glTexStorage2D() in order to access the texture via image2D in compute shaders. 15 | #ifdef PATHFINDER_ENABLE_D3D11 16 | glTexStorage2D(GL_TEXTURE_2D, 1, to_gl_texture_format(desc.format), desc.size.x, desc.size.y); 17 | #else 18 | // We can deduce the pixel data type by the texture format. 19 | DataType type = texture_format_to_data_type(desc.format); 20 | 21 | glTexImage2D(GL_TEXTURE_2D, 22 | 0, 23 | to_gl_texture_format(desc.format), 24 | desc.size.x, 25 | desc.size.y, 26 | 0, 27 | GL_RGBA, 28 | to_gl_data_type(type), 29 | nullptr); 30 | #endif 31 | 32 | glBindTexture(GL_TEXTURE_2D, 0); 33 | 34 | gl_check_error("create_texture"); 35 | 36 | DebugMarker::label_texture(gl_id_, label_); 37 | } 38 | 39 | TextureGl::TextureGl(uint32_t external_gl_id, const TextureDescriptor& desc) : Texture(desc) { 40 | gl_id_ = external_gl_id; 41 | wrapped = true; 42 | } 43 | 44 | TextureGl::~TextureGl() { 45 | if (wrapped) { 46 | return; 47 | } 48 | glDeleteTextures(1, &gl_id_); 49 | } 50 | 51 | uint32_t TextureGl::get_texture_id() const { 52 | return gl_id_; 53 | } 54 | 55 | void TextureGl::set_label(const std::string& label) { 56 | Texture::set_label(label); 57 | 58 | DebugMarker::label_texture(gl_id_, label); 59 | } 60 | 61 | } // namespace Pathfinder 62 | -------------------------------------------------------------------------------- /third_party/glfw/CMake/GenerateMappings.cmake: -------------------------------------------------------------------------------- 1 | # Usage: 2 | # cmake -P GenerateMappings.cmake 3 | 4 | set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt") 5 | set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt") 6 | set(template_path "${CMAKE_ARGV3}") 7 | set(target_path "${CMAKE_ARGV4}") 8 | 9 | if (NOT EXISTS "${template_path}") 10 | message(FATAL_ERROR "Failed to find template file ${template_path}") 11 | endif() 12 | 13 | file(DOWNLOAD "${source_url}" "${source_path}" 14 | STATUS download_status 15 | TLS_VERIFY on) 16 | 17 | list(GET download_status 0 status_code) 18 | list(GET download_status 1 status_message) 19 | 20 | if (status_code) 21 | message(FATAL_ERROR "Failed to download ${source_url}: ${status_message}") 22 | endif() 23 | 24 | file(STRINGS "${source_path}" lines) 25 | foreach(line ${lines}) 26 | if (line MATCHES "^[0-9a-fA-F]") 27 | if (line MATCHES "platform:Windows") 28 | if (GLFW_WIN32_MAPPINGS) 29 | string(APPEND GLFW_WIN32_MAPPINGS "\n") 30 | endif() 31 | string(APPEND GLFW_WIN32_MAPPINGS "\"${line}\",") 32 | elseif (line MATCHES "platform:Mac OS X") 33 | if (GLFW_COCOA_MAPPINGS) 34 | string(APPEND GLFW_COCOA_MAPPINGS "\n") 35 | endif() 36 | string(APPEND GLFW_COCOA_MAPPINGS "\"${line}\",") 37 | elseif (line MATCHES "platform:Linux") 38 | if (GLFW_LINUX_MAPPINGS) 39 | string(APPEND GLFW_LINUX_MAPPINGS "\n") 40 | endif() 41 | string(APPEND GLFW_LINUX_MAPPINGS "\"${line}\",") 42 | endif() 43 | endif() 44 | endforeach() 45 | 46 | configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX) 47 | file(REMOVE "${source_path}") 48 | 49 | -------------------------------------------------------------------------------- /third_party/glfw/src/posix_thread.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 POSIX - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2002-2006 Marcus Geelnard 5 | // Copyright (c) 2006-2017 Camilla Löwy 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | 28 | #include 29 | 30 | #define GLFW_POSIX_TLS_STATE _GLFWtlsPOSIX posix; 31 | #define GLFW_POSIX_MUTEX_STATE _GLFWmutexPOSIX posix; 32 | 33 | 34 | // POSIX-specific thread local storage data 35 | // 36 | typedef struct _GLFWtlsPOSIX 37 | { 38 | GLFWbool allocated; 39 | pthread_key_t key; 40 | } _GLFWtlsPOSIX; 41 | 42 | // POSIX-specific mutex data 43 | // 44 | typedef struct _GLFWmutexPOSIX 45 | { 46 | GLFWbool allocated; 47 | pthread_mutex_t handle; 48 | } _GLFWmutexPOSIX; 49 | 50 | -------------------------------------------------------------------------------- /pathfinder/gpu/window.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_WINDOW_H 2 | #define PATHFINDER_GPU_WINDOW_H 3 | 4 | #include "device.h" 5 | #include "swap_chain.h" 6 | 7 | struct GLFWwindow; 8 | 9 | namespace Pathfinder { 10 | 11 | class SwapChain; 12 | 13 | class Window { 14 | friend class WindowBuilder; 15 | friend class WindowBuilderGl; 16 | 17 | public: 18 | #ifdef __ANDROID__ 19 | explicit Window(const Vec2I& size); 20 | #else 21 | explicit Window(const Vec2I& size, GLFWwindow* window_handle); 22 | #endif 23 | 24 | virtual ~Window() = default; 25 | 26 | virtual void destroy() = 0; 27 | 28 | virtual std::shared_ptr get_swap_chain(const std::shared_ptr& device) = 0; 29 | 30 | Vec2I get_physical_size() const; 31 | 32 | Vec2I get_logical_size() const; 33 | 34 | Vec2I get_position() const; 35 | 36 | void hide(); 37 | 38 | void show(); 39 | 40 | bool get_resize_flag() const; 41 | 42 | bool is_minimized() const; 43 | 44 | void* get_glfw_handle() const; 45 | 46 | bool should_close(); 47 | 48 | /// GLFW: whenever the window size changed (by OS or user) this callback function executes. 49 | static void framebuffer_resize_callback(GLFWwindow* glfw_window, int width, int height); 50 | 51 | std::shared_ptr swapchain_; 52 | 53 | float get_dpi_scaling_factor() const; 54 | 55 | void set_dpi_scaling_factor(float scale); 56 | 57 | void set_window_title(const std::string& title) const; 58 | 59 | uint8_t window_index{}; 60 | 61 | protected: 62 | Vec2I physical_size_; 63 | 64 | bool just_resized_ = false; 65 | bool fullscreen_ = false; 66 | bool minimized_ = false; 67 | bool hidden_ = false; 68 | 69 | float dpi_scaling_factor_ = 1.0f; 70 | 71 | #ifndef __ANDROID__ 72 | GLFWwindow* glfw_window_{}; 73 | #endif 74 | }; 75 | 76 | } // namespace Pathfinder 77 | 78 | #endif // PATHFINDER_GPU_WINDOW_H 79 | -------------------------------------------------------------------------------- /third_party/glfw/src/win32_thread.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Win32 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2002-2006 Marcus Geelnard 5 | // Copyright (c) 2006-2017 Camilla Löwy 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | 28 | #include 29 | 30 | #define GLFW_WIN32_TLS_STATE _GLFWtlsWin32 win32; 31 | #define GLFW_WIN32_MUTEX_STATE _GLFWmutexWin32 win32; 32 | 33 | // Win32-specific thread local storage data 34 | // 35 | typedef struct _GLFWtlsWin32 36 | { 37 | GLFWbool allocated; 38 | DWORD index; 39 | } _GLFWtlsWin32; 40 | 41 | // Win32-specific mutex data 42 | // 43 | typedef struct _GLFWmutexWin32 44 | { 45 | GLFWbool allocated; 46 | CRITICAL_SECTION section; 47 | } _GLFWmutexWin32; 48 | 49 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | env: 10 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 11 | BUILD_TYPE: Release 12 | 13 | jobs: 14 | build: 15 | # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. 16 | # You can convert this to a matrix build if you need cross-platform coverage. 17 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 18 | runs-on: ubuntu-24.04 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | with: 23 | submodules: recursive 24 | 25 | - name: Install GLFW dependency 26 | run: sudo apt-get install xorg-dev 27 | 28 | - name: Prepare Vulkan SDK 29 | uses: humbletim/setup-vulkan-sdk@v1.2.1 30 | with: 31 | vulkan-query-version: 1.4.304.1 32 | vulkan-components: Vulkan-Headers, Vulkan-Loader 33 | vulkan-use-cache: true 34 | 35 | - name: Configure CMake 36 | # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. 37 | # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type 38 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 39 | 40 | - name: Build 41 | # Build your program with the given configuration 42 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 43 | 44 | - name: Test 45 | working-directory: ${{github.workspace}}/build 46 | # Execute tests defined by the CMake configuration. 47 | # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail 48 | run: ctest -C ${{env.BUILD_TYPE}} 49 | 50 | -------------------------------------------------------------------------------- /demo/android/.gitignore: -------------------------------------------------------------------------------- 1 | # C++ source 2 | app/src/main/cpp/src 3 | app/src/main/cpp/third_party 4 | 5 | # Built application files 6 | *.apk 7 | *.aar 8 | *.ap_ 9 | *.aab 10 | 11 | # Files for the ART/Dalvik VM 12 | *.dex 13 | 14 | # Java class files 15 | *.class 16 | 17 | # Generated files 18 | bin/ 19 | gen/ 20 | out/ 21 | # Uncomment the following line in case you need and you don't have the release build type files in your app 22 | # release/ 23 | 24 | # Gradle files 25 | .gradle/ 26 | build/ 27 | 28 | # Local configuration file (sdk path, etc) 29 | local.properties 30 | 31 | # Proguard folder generated by Eclipse 32 | proguard/ 33 | 34 | # Log Files 35 | *.log 36 | 37 | # Android Studio Navigation editor temp files 38 | .navigation/ 39 | 40 | # Android Studio captures folder 41 | captures/ 42 | 43 | # IntelliJ 44 | *.iml 45 | .idea/workspace.xml 46 | .idea/tasks.xml 47 | .idea/gradle.xml 48 | .idea/assetWizardSettings.xml 49 | .idea/dictionaries 50 | .idea/libraries 51 | .idea/jarRepositories.xml 52 | # Android Studio 3 in .gitignore file. 53 | .idea/caches 54 | .idea/modules.xml 55 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 56 | .idea/navEditor.xml 57 | 58 | # Keystore files 59 | # Uncomment the following lines if you do not want to check your keystore files in. 60 | #*.jks 61 | #*.keystore 62 | 63 | # External native build folder generated in Android Studio 2.2 and later 64 | .externalNativeBuild 65 | .cxx/ 66 | 67 | # Google Services (e.g. APIs or Firebase) 68 | # google-services.json 69 | 70 | # Freeline 71 | freeline.py 72 | freeline/ 73 | freeline_project_description.json 74 | 75 | # fastlane 76 | fastlane/report.xml 77 | fastlane/Preview.html 78 | fastlane/screenshots 79 | fastlane/test_output 80 | fastlane/readme.md 81 | 82 | # Version control 83 | vcs.xml 84 | 85 | # lint 86 | lint/intermediates/ 87 | lint/generated/ 88 | lint/outputs/ 89 | lint/tmp/ 90 | # lint/reports/ 91 | 92 | # Android Profiling 93 | *.hprof 94 | -------------------------------------------------------------------------------- /pathfinder/core/data/built_path.cpp: -------------------------------------------------------------------------------- 1 | #include "built_path.h" 2 | 3 | #include "data.h" 4 | #include "path.h" 5 | 6 | namespace Pathfinder { 7 | 8 | BuiltPath::BuiltPath(uint32_t path_id, 9 | RectF path_bounds, 10 | RectF view_box_bounds, 11 | FillRule _fill_rule, 12 | const std::shared_ptr &clip_path_id, 13 | const TilingPathInfo &tiling_path_info) 14 | : fill_rule(_fill_rule) { 15 | if (tiling_path_info.type == TilingPathInfo::Type::Draw) { 16 | paint_id = tiling_path_info.info.paint_id; 17 | } 18 | 19 | ctrl_byte = tiling_path_info.to_ctrl(); 20 | 21 | RectF tile_map_bounds = tiling_path_info.has_destructive_blend_mode() ? view_box_bounds : path_bounds; 22 | 23 | tile_bounds = round_rect_out_to_tile_bounds(tile_map_bounds); 24 | 25 | data.backdrops = std::vector(tile_bounds.width(), 0); 26 | 27 | data.tiles = DenseTileMap(tile_bounds, path_id, paint_id, ctrl_byte); 28 | 29 | if (tiling_path_info.type == TilingPathInfo::Type::Draw) { 30 | if (clip_path_id) { 31 | data.clip_tiles = std::make_shared>(tile_bounds, AlphaTileId(), 0, AlphaTileId(), 0); 32 | } 33 | } 34 | } 35 | 36 | BuiltDrawPath::BuiltDrawPath(const BuiltPath &built_path, 37 | const DrawPath &path_object, 38 | const PaintMetadata &paint_metadata) { 39 | blend_mode = path_object.blend_mode; 40 | occludes = paint_metadata.is_opaque && blend_mode_occludes_backdrop(blend_mode); 41 | 42 | path = built_path; 43 | clip_path_id = path_object.clip_path; 44 | // filter = paint_metadata.filter(); 45 | color_texture_info = paint_metadata.tile_batch_texture_info(); 46 | sampling_flags = TextureSamplingFlags(); 47 | mask_fill_rule = path_object.fill_rule; 48 | } 49 | 50 | } // namespace Pathfinder 51 | -------------------------------------------------------------------------------- /pathfinder/shaders/compile_and_convert.ps1: -------------------------------------------------------------------------------- 1 | Remove-Item -Path "generated" -Recurse 2 | 3 | New-Item -Path "generated" -ItemType Directory 4 | 5 | New-Variable -Name "GLSLC" -Visibility Public -Value "$env:VULKAN_SDK/Bin/glslc.exe" 6 | 7 | # Compile shaders. 8 | & $GLSLC blit.vert -o generated/blit_vert.spv 9 | & $GLSLC blit.frag -o generated/blit_frag.spv 10 | 11 | & $GLSLC d3d9/fill.vert -o generated/fill_vert.spv 12 | & $GLSLC d3d9/fill.frag -o generated/fill_frag.spv 13 | & $GLSLC d3d9/tile.vert -o generated/tile_vert.spv 14 | & $GLSLC d3d9/tile.frag -o generated/tile_frag.spv 15 | & $GLSLC d3d9/tile_clip_copy.vert -o generated/tile_clip_copy_vert.spv 16 | & $GLSLC d3d9/tile_clip_copy.frag -o generated/tile_clip_copy_frag.spv 17 | & $GLSLC d3d9/tile_clip_combine.vert -o generated/tile_clip_combine_vert.spv 18 | & $GLSLC d3d9/tile_clip_combine.frag -o generated/tile_clip_combine_frag.spv 19 | 20 | & $GLSLC d3d11/bin.comp -o generated/bin_comp.spv 21 | & $GLSLC d3d11/bound.comp -o generated/bound_comp.spv 22 | & $GLSLC d3d11/dice.comp -o generated/dice_comp.spv 23 | & $GLSLC d3d11/fill.comp -o generated/fill_comp.spv 24 | & $GLSLC d3d11/propagate.comp -o generated/propagate_comp.spv 25 | & $GLSLC d3d11/sort.comp -o generated/sort_comp.spv 26 | & $GLSLC d3d11/tile.comp -o generated/tile_comp.spv 27 | 28 | Copy-Item "area_lut.png" "generated" 29 | Copy-Item "blit.frag" "generated" 30 | Copy-Item "blit.vert" "generated" 31 | Copy-Item "d3d9/*.*" "generated" 32 | Copy-Item "d3d11/*.*" "generated" 33 | 34 | Set-Location "generated" 35 | 36 | # Generate headers. 37 | python ../convert_files_to_header.py vert 38 | python ../convert_files_to_header.py frag 39 | python ../convert_files_to_header.py comp 40 | python ../convert_files_to_header.py spv 41 | python ../convert_files_to_header.py png 42 | 43 | # Remove intermediate files. 44 | Get-ChildItem -Recurse -File | Where { ($_.Extension -ne ".h") } | Remove-Item 45 | 46 | # Wait for input. 47 | Write-Host "All jobs finished." 48 | $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") 49 | -------------------------------------------------------------------------------- /pathfinder/common/math/mat3.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_MAT3_H 2 | #define PATHFINDER_MAT3_H 3 | 4 | #include "vec2.h" 5 | 6 | namespace Pathfinder { 7 | 8 | /// A 3x3 matrix, in column-major order. 9 | struct Mat3 { 10 | float v[9] = {0}; 11 | 12 | Mat3() = default; 13 | 14 | explicit Mat3(float s) { 15 | for (int i = 0; i < 3; i++) { 16 | v[i * 3 + i] = s; 17 | } 18 | } 19 | 20 | static Mat3 from_scale(const Vec2F &scale) { 21 | auto mat = Mat3(1); 22 | 23 | mat.v[0] = scale.x; 24 | mat.v[4] = scale.y; 25 | 26 | return mat; 27 | } 28 | 29 | static Mat3 from_translation(const Vec2F &translation) { 30 | auto mat = Mat3(1); 31 | 32 | mat.v[6] = translation.x; 33 | mat.v[7] = translation.y; 34 | 35 | return mat; 36 | } 37 | 38 | static Mat3 from_rotation(float theta) { 39 | auto mat = Mat3(1); 40 | 41 | mat.v[0] = cos(theta); 42 | mat.v[3] = -sin(theta); 43 | mat.v[1] = sin(theta); 44 | mat.v[4] = cos(theta); 45 | 46 | return mat; 47 | } 48 | 49 | Mat3 operator*(const Mat3 &other) const { 50 | auto mat = Mat3(); 51 | 52 | for (int i = 0; i < 3; i++) { 53 | for (int j = 0; j < 3; j++) { 54 | auto index = i + j * 3; 55 | mat.v[index] = 0; 56 | for (int k = 0; k < 3; k++) { 57 | mat.v[index] += v[i + k * 3] * other.v[k + j * 3]; 58 | } 59 | } 60 | } 61 | 62 | return mat; 63 | } 64 | 65 | Mat3 translate(const Vec2F &translation) const { 66 | return *this * from_translation(translation); 67 | } 68 | 69 | Mat3 scale(const Vec2F &scale) const { 70 | return *this * from_scale(scale); 71 | } 72 | 73 | Mat3 rotate(float theta) const { 74 | return *this * from_rotation(theta); 75 | } 76 | }; 77 | 78 | } // namespace Pathfinder 79 | 80 | #endif // PATHFINDER_MAT3_H 81 | -------------------------------------------------------------------------------- /pathfinder/core/data/path.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_PATH_H 2 | #define PATHFINDER_PATH_H 3 | 4 | #include 5 | 6 | #include "contour.h" 7 | 8 | namespace Pathfinder { 9 | 10 | /// A vector path to be filled (without drawing info). 11 | /// In order to differentiate it from DrawPath and ClipPath, we use the name 'Outline' here. 12 | /// Outlines consist of contours (a.k.a. sub-paths). 13 | class Outline { 14 | public: 15 | std::vector contours; 16 | 17 | /// Bounding box. 18 | RectF bounds; 19 | 20 | public: 21 | /// Applies an affine transform to this shape and all its paths. 22 | void transform(const Transform2 &transform); 23 | 24 | /// Add a new contour to this shape. 25 | void push_contour(const Contour &_contour); 26 | }; 27 | 28 | /// A thin wrapper over Outline, which describes a path that can be drawn. 29 | struct DrawPath { 30 | /// The actual vector path. 31 | Outline outline; 32 | 33 | /// The ID of the paint that specifies how to fill this shape. 34 | uint16_t paint{}; 35 | 36 | /// The ID of an optional clip shape that will be used to clip this shape. 37 | std::shared_ptr clip_path; // Optional 38 | 39 | /// How to fill this shape (winding or even-odd). 40 | FillRule fill_rule = FillRule::Winding; 41 | 42 | /// How to blend this shape with everything below it. 43 | BlendMode blend_mode = BlendMode::SrcOver; 44 | }; 45 | 46 | /// A thin wrapper over Outline, which describes a path that can be used to clip other paths. 47 | struct ClipPath { 48 | /// The actual vector path. 49 | Outline outline; 50 | 51 | /// The ID of another, previously-defined, clip path that clips this one. 52 | /// 53 | /// Nested clips can be achieved by clipping clip paths with other clip paths. 54 | std::shared_ptr clip_path; // Optional 55 | 56 | /// How to fill this shape (winding or even-odd). 57 | FillRule fill_rule = FillRule::Winding; 58 | }; 59 | 60 | } // namespace Pathfinder 61 | 62 | #endif // PATHFINDER_PATH_H 63 | -------------------------------------------------------------------------------- /pathfinder/core/stroke.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_STROKE_H 2 | #define PATHFINDER_STROKE_H 3 | 4 | //! Utilities for converting contour strokes to fills. 5 | 6 | #include 7 | 8 | #include "data/contour.h" 9 | #include "data/path.h" 10 | #include "data/segment.h" 11 | 12 | namespace Pathfinder { 13 | 14 | /// How an outline should be stroked. 15 | struct StrokeStyle { 16 | /// The width of the stroke in scene units. 17 | float line_width = 1.0f; 18 | 19 | /// The shape of the ends of the stroke. 20 | LineCap line_cap = LineCap::Butt; 21 | 22 | /// The shape used to join two line segments where they meet. 23 | LineJoin line_join = LineJoin::Miter; 24 | 25 | /// Only for LineJoin::Miter. 26 | float miter_limit = 10.0f; 27 | }; 28 | 29 | /// Contour stroke to fill. 30 | struct ContourStrokeToFill { 31 | Contour input; 32 | Contour output; 33 | float radius; 34 | LineJoin join; 35 | float join_miter_limit = 10; // Only used when line join is miter. 36 | 37 | ContourStrokeToFill(Contour _input, float _radius, LineJoin _join, float _join_miter_limit); 38 | 39 | /// Scale the input contour up, forming an outer contour. 40 | void offset_forward(); 41 | 42 | /// Scale the input contour down, forming an inner contour. 43 | void offset_backward(); 44 | }; 45 | 46 | /// Strokes an outline with a stroke style to produce a new shape. 47 | struct OutlineStrokeToFill { 48 | const Outline &input; 49 | Outline output{}; 50 | StrokeStyle style; 51 | 52 | OutlineStrokeToFill(const Outline &_input, StrokeStyle _style); 53 | 54 | /// Performs the stroke operation. 55 | void offset(); 56 | 57 | /// Returns the resulting stroked outline. This should be called after `offset()`. 58 | Outline into_outline() const; 59 | 60 | void push_stroked_contour(std::vector &new_contours, ContourStrokeToFill stroker, bool closed) const; 61 | 62 | void add_cap(Contour &contour) const; 63 | }; 64 | 65 | } // namespace Pathfinder 66 | 67 | #endif // PATHFINDER_STROKE_H 68 | -------------------------------------------------------------------------------- /pathfinder/core/data/built_path.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_BUILT_PATH_H 2 | #define PATHFINDER_BUILT_PATH_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../../common/math/rect.h" 9 | #include "../d3d9/data/gpu_data.h" 10 | #include "../paint/paint.h" 11 | #include "data.h" 12 | #include "dense_tile_map.h" 13 | #include "path.h" 14 | 15 | namespace Pathfinder { 16 | 17 | struct BuiltPathData { 18 | /// During tiling, or if backdrop computation is done on GPU, this stores the sum of backdrops 19 | /// for tile columns above the viewport. 20 | std::vector backdrops; 21 | DenseTileMap tiles; 22 | std::shared_ptr> clip_tiles; 23 | }; 24 | 25 | struct BuiltPath { 26 | BuiltPathData data; 27 | RectI tile_bounds; 28 | FillRule fill_rule = FillRule::Winding; 29 | std::shared_ptr clip_path_id; 30 | uint8_t ctrl_byte = 0; 31 | uint16_t paint_id = 0; 32 | 33 | BuiltPath() = default; 34 | 35 | BuiltPath(uint32_t path_id, 36 | RectF path_bounds, 37 | RectF view_box_bounds, 38 | FillRule _fill_rule, 39 | const std::shared_ptr &clip_path_id, 40 | const TilingPathInfo &tiling_path_info); 41 | }; 42 | 43 | /// This stores a built path with extra info related to its drawing. 44 | struct BuiltDrawPath { 45 | BuiltPath path; 46 | std::shared_ptr clip_path_id; 47 | BlendMode blend_mode; 48 | // Filter filter; 49 | std::shared_ptr color_texture_info; // Will be used in tile batch building. 50 | TextureSamplingFlags sampling_flags; 51 | FillRule mask_fill_rule; 52 | 53 | /// If the path is opaque. Used to determine z buffer. 54 | bool occludes = true; 55 | 56 | BuiltDrawPath() = default; 57 | BuiltDrawPath(const BuiltPath &built_path, const DrawPath &path_object, const PaintMetadata &paint_metadata); 58 | }; 59 | 60 | } // namespace Pathfinder 61 | 62 | #endif // PATHFINDER_BUILT_PATH_H 63 | -------------------------------------------------------------------------------- /third_party/glfw/src/cocoa_joystick.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Cocoa - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2006-2017 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns; 32 | #define GLFW_COCOA_LIBRARY_JOYSTICK_STATE 33 | 34 | // Cocoa-specific per-joystick data 35 | // 36 | typedef struct _GLFWjoystickNS 37 | { 38 | IOHIDDeviceRef device; 39 | CFMutableArrayRef axes; 40 | CFMutableArrayRef buttons; 41 | CFMutableArrayRef hats; 42 | } _GLFWjoystickNS; 43 | 44 | GLFWbool _glfwInitJoysticksCocoa(void); 45 | void _glfwTerminateJoysticksCocoa(void); 46 | GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode); 47 | const char* _glfwGetMappingNameCocoa(void); 48 | void _glfwUpdateGamepadGUIDCocoa(char* guid); 49 | 50 | -------------------------------------------------------------------------------- /pathfinder/common/math/mat4.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_MAT4_H 2 | #define PATHFINDER_MAT4_H 3 | 4 | #include "mat3.h" 5 | #include "vec3.h" 6 | 7 | namespace Pathfinder { 8 | 9 | /// A 4x4 matrix, in column-major order. 10 | struct Mat4 { 11 | float v[16] = {0}; 12 | 13 | Mat4() = default; 14 | 15 | explicit Mat4(float s) { 16 | for (int i = 0; i < 4; i++) { 17 | v[i * 4 + i] = s; 18 | } 19 | } 20 | 21 | static Mat4 from_mat3(Mat3 mat3) { 22 | auto mat = Mat4(1); 23 | 24 | mat.v[0] = mat3.v[0]; 25 | mat.v[4] = mat3.v[3]; 26 | mat.v[1] = mat3.v[1]; 27 | mat.v[5] = mat3.v[4]; 28 | 29 | mat.v[12] = mat3.v[6]; 30 | mat.v[13] = mat3.v[7]; 31 | 32 | return mat; 33 | } 34 | 35 | static Mat4 from_scale(const Vec3F &scale) { 36 | auto mat = Mat4(1); 37 | 38 | mat.v[0] = scale.x; 39 | mat.v[5] = scale.y; 40 | mat.v[10] = scale.z; 41 | 42 | return mat; 43 | } 44 | 45 | static Mat4 from_translation(const Vec3F &translation) { 46 | auto mat = Mat4(1); 47 | 48 | mat.v[12] = translation.x; 49 | mat.v[13] = translation.y; 50 | mat.v[14] = translation.z; 51 | 52 | return mat; 53 | } 54 | 55 | Mat4 operator*(const Mat4 &other) const { 56 | auto mat = Mat4(); 57 | 58 | for (int i = 0; i < 4; i++) { 59 | for (int j = 0; j < 4; j++) { 60 | auto index = i + j * 4; 61 | mat.v[index] = 0; 62 | for (int k = 0; k < 4; k++) { 63 | mat.v[index] += v[i + k * 4] * other.v[k + j * 4]; 64 | } 65 | } 66 | } 67 | 68 | return mat; 69 | } 70 | 71 | Mat4 translate(const Vec3F &translation) const { 72 | return *this * from_translation(translation); 73 | } 74 | 75 | Mat4 scale(const Vec3F &scale) const { 76 | return *this * from_scale(scale); 77 | } 78 | }; 79 | 80 | } // namespace Pathfinder 81 | 82 | #endif // PATHFINDER_MAT4_H 83 | -------------------------------------------------------------------------------- /third_party/glfw/src/win32_joystick.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Win32 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2006-2017 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | #define GLFW_WIN32_JOYSTICK_STATE _GLFWjoystickWin32 win32; 28 | #define GLFW_WIN32_LIBRARY_JOYSTICK_STATE 29 | 30 | // Joystick element (axis, button or slider) 31 | // 32 | typedef struct _GLFWjoyobjectWin32 33 | { 34 | int offset; 35 | int type; 36 | } _GLFWjoyobjectWin32; 37 | 38 | // Win32-specific per-joystick data 39 | // 40 | typedef struct _GLFWjoystickWin32 41 | { 42 | _GLFWjoyobjectWin32* objects; 43 | int objectCount; 44 | IDirectInputDevice8W* device; 45 | DWORD index; 46 | GUID guid; 47 | } _GLFWjoystickWin32; 48 | 49 | void _glfwDetectJoystickConnectionWin32(void); 50 | void _glfwDetectJoystickDisconnectionWin32(void); 51 | 52 | -------------------------------------------------------------------------------- /pathfinder/common/color.cpp: -------------------------------------------------------------------------------- 1 | #include "color.h" 2 | 3 | namespace Pathfinder { 4 | 5 | // ColorU 6 | // -------------------- 7 | ColorU::ColorU(uint32_t color) { 8 | // Note that the order is reversed. 9 | a_ = color >> 24u; 10 | b_ = (color << 8u) >> 24u; 11 | g_ = (color << 16u) >> 24u; 12 | r_ = (color << 24u) >> 24u; 13 | } 14 | 15 | ColorU::ColorU(const ColorF& color) { 16 | // Note that the order is reversed. 17 | a_ = static_cast(color.a_ * 255.f); 18 | b_ = static_cast(color.b_ * 255.f); 19 | g_ = static_cast(color.g_ * 255.f); 20 | r_ = static_cast(color.r_ * 255.f); 21 | } 22 | 23 | ColorU::ColorU(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r_(r), g_(g), b_(b), a_(a) {} 24 | 25 | ColorU::ColorU(uint8_t r, uint8_t g, uint8_t b) : r_(r), g_(g), b_(b), a_(255) {} 26 | 27 | uint32_t ColorU::to_u32() const { 28 | uint32_t rgba = (r_ << 24u) + (g_ << 16u) + (b_ << 8u) + a_; 29 | 30 | return rgba; 31 | } 32 | 33 | ColorF ColorU::to_f32() const { 34 | float factor = 1.f / 255.f; 35 | 36 | return {static_cast(r_) * factor, 37 | static_cast(g_) * factor, 38 | static_cast(b_) * factor, 39 | static_cast(a_) * factor}; 40 | } 41 | 42 | bool ColorU::is_opaque() const { 43 | return a_ != 0; 44 | } 45 | 46 | ColorU ColorU::lerp(const ColorU& other, float t) const { 47 | auto ret = ColorU(to_f32().lerp(other.to_f32(), t)); 48 | return ret; 49 | } 50 | 51 | // -------------------- 52 | 53 | // ColorF 54 | // -------------------- 55 | ColorF::ColorF(float r, float g, float b, float a) : r_(r), g_(g), b_(b), a_(a) {} 56 | 57 | ColorF ColorF::lerp(const ColorF& other, float t) const { 58 | assert(t >= 0 && t <= 1); 59 | t = clamp(t, 0.0f, 1.0f); 60 | 61 | auto ret = ColorF{ 62 | r_ + (other.r_ - r_) * t, 63 | g_ + (other.g_ - g_) * t, 64 | b_ + (other.b_ - b_) * t, 65 | a_ + (other.a_ - a_) * t, 66 | }; 67 | 68 | return ret; 69 | } 70 | // -------------------- 71 | 72 | } // namespace Pathfinder 73 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/blit_frag.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_BLIT_FRAG_H 2 | #define PATHFINDER_RESOURCE_BLIT_FRAG_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t blit_frag[] = {35,118,101,114,115,105,111,110,32,51,49,48,32,101,115,13,10,13,10,35,105,102,100,101,102,32,71,76,95,69,83,13,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,102,108,111,97,116,59,13,10,112,114,101,99,105,115,105,111,110,32,104,105,103,104,112,32,115,97,109,112,108,101,114,50,68,59,13,10,35,101,110,100,105,102,13,10,13,10,35,105,102,100,101,102,32,86,85,76,75,65,78,13,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,111,117,116,32,118,101,99,52,32,111,70,114,97,103,67,111,108,111,114,59,13,10,13,10,108,97,121,111,117,116,40,108,111,99,97,116,105,111,110,32,61,32,48,41,32,105,110,32,118,101,99,50,32,118,85,86,59,13,10,13,10,108,97,121,111,117,116,40,98,105,110,100,105,110,103,32,61,32,48,41,32,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,117,84,101,120,116,117,114,101,59,13,10,35,101,108,115,101,13,10,111,117,116,32,118,101,99,52,32,111,70,114,97,103,67,111,108,111,114,59,13,10,13,10,105,110,32,118,101,99,50,32,118,85,86,59,13,10,13,10,117,110,105,102,111,114,109,32,115,97,109,112,108,101,114,50,68,32,117,84,101,120,116,117,114,101,59,13,10,35,101,110,100,105,102,13,10,13,10,118,111,105,100,32,109,97,105,110,40,41,32,123,13,10,32,32,32,32,47,47,32,87,104,101,110,32,100,114,97,119,105,110,103,32,116,111,32,116,104,101,32,115,99,114,101,101,110,44,32,119,101,32,110,101,101,100,32,116,111,32,102,108,105,112,32,116,104,101,32,116,101,120,116,117,114,101,32,102,111,114,32,71,76,46,13,10,35,105,102,100,101,102,32,86,85,76,75,65,78,13,10,32,32,32,32,111,70,114,97,103,67,111,108,111,114,32,61,32,116,101,120,116,117,114,101,40,117,84,101,120,116,117,114,101,44,32,118,85,86,41,59,13,10,35,101,108,115,101,13,10,32,32,32,32,111,70,114,97,103,67,111,108,111,114,32,61,32,116,101,120,116,117,114,101,40,117,84,101,120,116,117,114,101,44,32,118,101,99,50,40,118,85,86,46,120,44,32,49,46,48,102,32,45,32,118,85,86,46,121,41,41,59,13,10,35,101,110,100,105,102,13,10,125,13,10}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_BLIT_FRAG_H 9 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/queue.cpp: -------------------------------------------------------------------------------- 1 | #include "queue.h" 2 | 3 | #include "fence.h" 4 | 5 | namespace Pathfinder { 6 | 7 | void QueueVk::submit(const std::shared_ptr &encoder, const std::shared_ptr &fence) { 8 | if (encoder->submitted_) { 9 | Logger::error("Attempted to submit an encoder that's already been submitted!"); 10 | return; 11 | } 12 | 13 | // Mark the encoder as submitted. 14 | encoder->submitted_ = true; 15 | 16 | if (!encoder->finish()) { 17 | return; 18 | } 19 | 20 | auto encoder_vk = (CommandEncoderVk *)encoder.get(); 21 | 22 | // Submit the command buffer to the graphics queue. 23 | VkSubmitInfo submit_info{}; 24 | submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 25 | submit_info.commandBufferCount = 1; 26 | submit_info.pCommandBuffers = &encoder_vk->vk_command_buffer_; 27 | 28 | if (fence) { 29 | auto fence_vk = (FenceVk *)fence.get(); 30 | 31 | vkQueueSubmit(vk_graphics_queue_, 1, &submit_info, fence_vk->fence); 32 | 33 | fence_vk->wait(); 34 | } else { 35 | vkQueueSubmit(vk_graphics_queue_, 1, &submit_info, VK_NULL_HANDLE); 36 | } 37 | } 38 | 39 | void QueueVk::submit_and_wait(const std::shared_ptr &encoder) { 40 | if (encoder->submitted_) { 41 | Logger::error("Attempted to submit an encoder that's already been submitted!"); 42 | return; 43 | } 44 | 45 | // Mark the encoder as submitted. 46 | encoder->submitted_ = true; 47 | 48 | if (!encoder->finish()) { 49 | return; 50 | } 51 | 52 | auto encoder_vk = (CommandEncoderVk *)encoder.get(); 53 | 54 | // Submit the command buffer to the graphics queue. 55 | VkSubmitInfo submit_info{}; 56 | submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 57 | submit_info.commandBufferCount = 1; 58 | submit_info.pCommandBuffers = &encoder_vk->vk_command_buffer_; 59 | 60 | vkQueueSubmit(vk_graphics_queue_, 1, &submit_info, VK_NULL_HANDLE); 61 | 62 | // Wait for the queue to finish commands. 63 | vkQueueWaitIdle(vk_graphics_queue_); 64 | } 65 | 66 | } // namespace Pathfinder 67 | -------------------------------------------------------------------------------- /third_party/glfw/src/null_joystick.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2016-2017 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | // It is fine to use C99 in this file because it will not be built with VS 27 | //======================================================================== 28 | 29 | #include "internal.h" 30 | 31 | 32 | ////////////////////////////////////////////////////////////////////////// 33 | ////// GLFW platform API ////// 34 | ////////////////////////////////////////////////////////////////////////// 35 | 36 | GLFWbool _glfwInitJoysticksNull(void) 37 | { 38 | return GLFW_TRUE; 39 | } 40 | 41 | void _glfwTerminateJoysticksNull(void) 42 | { 43 | } 44 | 45 | GLFWbool _glfwPollJoystickNull(_GLFWjoystick* js, int mode) 46 | { 47 | return GLFW_FALSE; 48 | } 49 | 50 | const char* _glfwGetMappingNameNull(void) 51 | { 52 | return ""; 53 | } 54 | 55 | void _glfwUpdateGamepadGUIDNull(char* guid) 56 | { 57 | } 58 | 59 | -------------------------------------------------------------------------------- /pathfinder/gpu/texture.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_TEXTURE_H 2 | #define PATHFINDER_GPU_TEXTURE_H 3 | 4 | #include "../common/math/vec2.h" 5 | #include "base.h" 6 | 7 | namespace Pathfinder { 8 | 9 | struct TextureDescriptor { 10 | Vec2I size; 11 | TextureFormat format; 12 | 13 | size_t byte_size() const { 14 | return size.area() * get_pixel_size(format); 15 | } 16 | 17 | bool operator==(const TextureDescriptor& b) const { 18 | return size == b.size && format == b.format; 19 | } 20 | }; 21 | 22 | struct SamplerDescriptor { 23 | SamplerFilter mag_filter; 24 | SamplerFilter min_filter; 25 | SamplerAddressMode address_mode_u; 26 | SamplerAddressMode address_mode_v; 27 | 28 | bool operator==(const SamplerDescriptor& rhs) const { 29 | return mag_filter == rhs.mag_filter && min_filter == rhs.min_filter && address_mode_u == rhs.address_mode_u && 30 | address_mode_v == rhs.address_mode_v; 31 | } 32 | }; 33 | 34 | class Sampler { 35 | friend class DeviceGl; 36 | 37 | public: 38 | virtual ~Sampler() = default; 39 | 40 | SamplerDescriptor get_descriptor() const { 41 | return descriptor_; 42 | } 43 | 44 | protected: 45 | explicit Sampler(const SamplerDescriptor& descriptor) : descriptor_(descriptor) {} 46 | 47 | SamplerDescriptor descriptor_; 48 | }; 49 | 50 | class Texture { 51 | public: 52 | virtual ~Texture() = default; 53 | 54 | Vec2I get_size() const { 55 | return desc_.size; 56 | } 57 | 58 | TextureFormat get_format() const { 59 | return desc_.format; 60 | } 61 | 62 | // Sometimes, we need to update label for a texture as we reuse it for another purpose. 63 | virtual void set_label(const std::string& label) { 64 | label_ = label; 65 | } 66 | 67 | std::string get_label() const { 68 | return label_; 69 | } 70 | 71 | protected: 72 | explicit Texture(TextureDescriptor desc) : desc_(desc) {} 73 | 74 | TextureDescriptor desc_; 75 | 76 | bool resource_ownership_ = true; 77 | 78 | std::string label_; 79 | }; 80 | 81 | } // namespace Pathfinder 82 | 83 | #endif // PATHFINDER_GPU_TEXTURE_H 84 | -------------------------------------------------------------------------------- /third_party/glfw/src/win32_module.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Win32 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2021 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | // Please use C89 style variable declarations in this file because VS 2010 27 | //======================================================================== 28 | 29 | #include "internal.h" 30 | 31 | #if defined(GLFW_BUILD_WIN32_MODULE) 32 | 33 | ////////////////////////////////////////////////////////////////////////// 34 | ////// GLFW platform API ////// 35 | ////////////////////////////////////////////////////////////////////////// 36 | 37 | void* _glfwPlatformLoadModule(const char* path) 38 | { 39 | return LoadLibraryA(path); 40 | } 41 | 42 | void _glfwPlatformFreeModule(void* module) 43 | { 44 | FreeLibrary((HMODULE) module); 45 | } 46 | 47 | GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name) 48 | { 49 | return (GLFWproc) GetProcAddress((HMODULE) module, name); 50 | } 51 | 52 | #endif // GLFW_BUILD_WIN32_MODULE 53 | 54 | -------------------------------------------------------------------------------- /third_party/glfw/src/posix_module.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 POSIX - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2021 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | // It is fine to use C99 in this file because it will not be built with VS 27 | //======================================================================== 28 | 29 | #include "internal.h" 30 | 31 | #if defined(GLFW_BUILD_POSIX_MODULE) 32 | 33 | #include 34 | 35 | ////////////////////////////////////////////////////////////////////////// 36 | ////// GLFW platform API ////// 37 | ////////////////////////////////////////////////////////////////////////// 38 | 39 | void* _glfwPlatformLoadModule(const char* path) 40 | { 41 | return dlopen(path, RTLD_LAZY | RTLD_LOCAL); 42 | } 43 | 44 | void _glfwPlatformFreeModule(void* module) 45 | { 46 | dlclose(module); 47 | } 48 | 49 | GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name) 50 | { 51 | return dlsym(module, name); 52 | } 53 | 54 | #endif // GLFW_BUILD_POSIX_MODULE 55 | 56 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d9/fill.frag: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | // pathfinder/shaders/fill.fs.glsl 4 | // 5 | // Copyright © 2020 The Pathfinder Project Developers. 6 | // 7 | // Licensed under the Apache License, Version 2.0 or the MIT license 9 | // , at your 10 | // option. This file may not be copied, modified, or distributed 11 | // except according to those terms. 12 | 13 | #ifdef GL_ES 14 | precision highp float; 15 | precision highp sampler2D; 16 | #endif 17 | 18 | // Pre-prepared texture "area-lut.png" of size (256, 256). 19 | #ifdef VULKAN 20 | layout(binding = 1) uniform sampler2D uAreaLUT; 21 | 22 | layout(location = 0) in vec2 vFrom; 23 | layout(location = 1) in vec2 vTo; 24 | layout(location = 0) out vec4 oFragColor; 25 | #else 26 | uniform sampler2D uAreaLUT; 27 | 28 | in vec2 vFrom; 29 | in vec2 vTo; 30 | out vec4 oFragColor; 31 | #endif 32 | 33 | /// Understanding this process is quite hard as we need to understand the areaLUT texture first. 34 | /// But I guess areaLUT is mostly used for anti-aliasing. 35 | vec4 computeCoverage(vec2 from, vec2 to, sampler2D areaLUT) { 36 | // Determine winding, and sort into a consistent order so we only need to find one root below. 37 | vec2 left = from.x < to.x ? from : to, right = from.x < to.x ? to : from; 38 | 39 | // Shoot a vertical ray toward the curve. 40 | vec2 window = clamp(vec2(from.x, to.x), -0.5, 0.5); 41 | float offset = mix(window.x, window.y, 0.5) - left.x; 42 | 43 | // On-segment coordinate. 44 | float t = offset / (right.x - left.x); 45 | 46 | // Compute position and derivative to form a line approximation. 47 | float y = mix(left.y, right.y, t);// Scanline hit position y calculated from t. 48 | float d = (right.y - left.y) / (right.x - left.x);// Derivative of the line segment. 49 | 50 | // Look up area under that line, and scale horizontally to the window size. 51 | float dX = window.x - window.y; 52 | 53 | // Sample data from the areaLUT texture. 54 | return texture(areaLUT, vec2(y + 8.0, abs(d * dX)) / 16.0) * dX; 55 | } 56 | 57 | void main() { 58 | oFragColor = computeCoverage(vFrom, vTo, uAreaLUT); 59 | } 60 | -------------------------------------------------------------------------------- /pathfinder/gpu/window_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_WINDOW_BUILDER_H 2 | #define PATHFINDER_WINDOW_BUILDER_H 3 | 4 | #include "device.h" 5 | #include "queue.h" 6 | 7 | #ifdef __ANDROID__ 8 | #include 9 | #endif 10 | 11 | class ANativeWindow; 12 | struct GLFWwindow; 13 | 14 | namespace Pathfinder { 15 | 16 | class Window; 17 | 18 | static const char *PRIMARY_WINDOW_TITLE = "Primary Window"; 19 | 20 | /// Window management. 21 | class WindowBuilder { 22 | public: 23 | static std::shared_ptr new_impl(BackendType backend_type, const Vec2I &size); 24 | 25 | virtual ~WindowBuilder() = default; 26 | 27 | /// Wait for the swapchains to finish the current frame, then destroy them. 28 | /// Call this right after the render loop is stopped. 29 | virtual void stop_and_destroy_swapchains() {} 30 | 31 | /// Create a new sub-window. 32 | virtual uint8_t create_window(const Vec2I &size, const std::string &title) = 0; 33 | 34 | std::weak_ptr get_window(uint8_t window_index) const; 35 | 36 | float get_dpi_scaling_factor(uint8_t window_index) const; 37 | 38 | void set_dpi_scaling_factor(uint8_t window_index, float new_scale); 39 | 40 | virtual std::shared_ptr request_device() = 0; 41 | 42 | virtual std::shared_ptr create_queue() = 0; 43 | 44 | void poll_events(); 45 | 46 | void set_fullscreen(bool fullscreen); 47 | 48 | protected: 49 | #ifndef __ANDROID__ 50 | static GLFWwindow *glfw_window_init(const Vec2I &logical_size, 51 | const std::string &title, 52 | float &dpi_scaling_factor, 53 | bool fullscreen, 54 | GLFWwindow *shared_window); 55 | #else 56 | ANativeWindow *native_window_{}; 57 | #endif 58 | 59 | std::shared_ptr primary_window_; 60 | std::vector> sub_windows_; 61 | 62 | bool primary_window_fullscreen_ = false; 63 | 64 | // Size before going fullscreen or being minimized. 65 | Vec2I reserved_window_physical_size_; 66 | 67 | Vec2I reserved_window_position_; 68 | }; 69 | 70 | } // namespace Pathfinder 71 | 72 | #endif // PATHFINDER_WINDOW_BUILDER_H 73 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/blit_vert_spv.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_BLIT_VERT_SPV_H 2 | #define PATHFINDER_RESOURCE_BLIT_VERT_SPV_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t blit_vert_spv[] = {3,2,35,7,0,0,1,0,11,0,13,0,28,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,9,0,0,0,0,0,4,0,0,0,109,97,105,110,0,0,0,0,9,0,0,0,11,0,0,0,16,0,0,0,19,0,0,0,3,0,3,0,1,0,0,0,54,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5,0,3,0,9,0,0,0,118,85,86,0,5,0,3,0,11,0,0,0,97,85,86,0,5,0,6,0,14,0,0,0,103,108,95,80,101,114,86,101,114,116,101,120,0,0,0,0,6,0,6,0,14,0,0,0,0,0,0,0,103,108,95,80,111,115,105,116,105,111,110,0,6,0,7,0,14,0,0,0,1,0,0,0,103,108,95,80,111,105,110,116,83,105,122,101,0,0,0,0,5,0,3,0,16,0,0,0,0,0,0,0,5,0,4,0,19,0,0,0,97,80,111,115,0,0,0,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,11,0,0,0,30,0,0,0,1,0,0,0,72,0,5,0,14,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,72,0,5,0,14,0,0,0,1,0,0,0,11,0,0,0,1,0,0,0,71,0,3,0,14,0,0,0,2,0,0,0,71,0,4,0,19,0,0,0,30,0,0,0,0,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,2,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,32,0,4,0,10,0,0,0,1,0,0,0,7,0,0,0,59,0,4,0,10,0,0,0,11,0,0,0,1,0,0,0,23,0,4,0,13,0,0,0,6,0,0,0,4,0,0,0,30,0,4,0,14,0,0,0,13,0,0,0,6,0,0,0,32,0,4,0,15,0,0,0,3,0,0,0,14,0,0,0,59,0,4,0,15,0,0,0,16,0,0,0,3,0,0,0,21,0,4,0,17,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,17,0,0,0,18,0,0,0,0,0,0,0,59,0,4,0,10,0,0,0,19,0,0,0,1,0,0,0,43,0,4,0,6,0,0,0,21,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,22,0,0,0,0,0,128,63,32,0,4,0,26,0,0,0,3,0,0,0,13,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,61,0,4,0,7,0,0,0,12,0,0,0,11,0,0,0,62,0,3,0,9,0,0,0,12,0,0,0,61,0,4,0,7,0,0,0,20,0,0,0,19,0,0,0,81,0,5,0,6,0,0,0,23,0,0,0,20,0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,24,0,0,0,20,0,0,0,1,0,0,0,80,0,7,0,13,0,0,0,25,0,0,0,23,0,0,0,24,0,0,0,21,0,0,0,22,0,0,0,65,0,5,0,26,0,0,0,27,0,0,0,16,0,0,0,18,0,0,0,62,0,3,0,27,0,0,0,25,0,0,0,253,0,1,0,56,0,1,0}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_BLIT_VERT_SPV_H 9 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d9/tile_clip_combine.vert: -------------------------------------------------------------------------------- 1 | #version 310 es 2 | 3 | // pathfinder/shaders/tile_clip_combine.vs.glsl 4 | // 5 | // Copyright © 2020 The Pathfinder Project Developers. 6 | // 7 | // Licensed under the Apache License, Version 2.0 or the MIT license 9 | // , at your 10 | // option. This file may not be copied, modified, or distributed 11 | // except according to those terms. 12 | 13 | precision highp float; 14 | 15 | #ifdef GL_ES 16 | precision highp sampler2D; 17 | #endif 18 | 19 | #ifdef VULKAN 20 | layout(binding = 0) uniform bUniform { 21 | #else 22 | layout(std140) uniform bUniform { 23 | #endif 24 | vec2 uTileSize; // Fixed as (16, 16). 25 | vec2 uFramebufferSize; // Mask framebuffer. Dynamic as (4096, 1024 * page_count). 26 | }; 27 | 28 | #ifdef VULKAN 29 | layout(location = 0) in uvec2 aTileOffset; 30 | layout(location = 1) in int aDestTileIndex; 31 | layout(location = 2) in int aDestBackdrop; 32 | layout(location = 3) in int aSrcTileIndex; 33 | layout(location = 4) in int aSrcBackdrop; 34 | 35 | layout(location = 0) out vec2 vTexCoord0; 36 | layout(location = 1) out float vBackdrop0; 37 | layout(location = 2) out vec2 vTexCoord1; 38 | layout(location = 3) out float vBackdrop1; 39 | #else 40 | in uvec2 aTileOffset; 41 | in int aDestTileIndex; 42 | in int aDestBackdrop; 43 | in int aSrcTileIndex; 44 | in int aSrcBackdrop; 45 | 46 | out vec2 vTexCoord0; 47 | out float vBackdrop0; 48 | out vec2 vTexCoord1; 49 | out float vBackdrop1; 50 | #endif 51 | 52 | void main() { 53 | vec2 destPosition = vec2(ivec2(aDestTileIndex % 256, aDestTileIndex / 256) + ivec2(aTileOffset)); 54 | vec2 srcPosition = vec2(ivec2(aSrcTileIndex % 256, aSrcTileIndex / 256) + ivec2(aTileOffset)); 55 | destPosition *= vec2(16.0, 4.0) / uFramebufferSize; 56 | srcPosition *= vec2(16.0, 4.0) / uFramebufferSize; 57 | 58 | vTexCoord0 = destPosition; 59 | vTexCoord1 = srcPosition; 60 | 61 | vBackdrop0 = float(aDestBackdrop); 62 | vBackdrop1 = float(aSrcBackdrop); 63 | 64 | if (aDestTileIndex < 0) { 65 | destPosition = vec2(0.0); 66 | } 67 | 68 | gl_Position = vec4(mix(vec2(-1.0), vec2(1.0), destPosition), 0.0, 1.0); 69 | } 70 | -------------------------------------------------------------------------------- /third_party/glfw/src/cocoa_time.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 macOS - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2009-2016 Camilla Löwy 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | // It is fine to use C99 in this file because it will not be built with VS 27 | //======================================================================== 28 | 29 | #include "internal.h" 30 | 31 | #if defined(GLFW_BUILD_COCOA_TIMER) 32 | 33 | #include 34 | 35 | 36 | ////////////////////////////////////////////////////////////////////////// 37 | ////// GLFW platform API ////// 38 | ////////////////////////////////////////////////////////////////////////// 39 | 40 | void _glfwPlatformInitTimer(void) 41 | { 42 | mach_timebase_info_data_t info; 43 | mach_timebase_info(&info); 44 | 45 | _glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer; 46 | } 47 | 48 | uint64_t _glfwPlatformGetTimerValue(void) 49 | { 50 | return mach_absolute_time(); 51 | } 52 | 53 | uint64_t _glfwPlatformGetTimerFrequency(void) 54 | { 55 | return _glfw.timer.ns.frequency; 56 | } 57 | 58 | #endif // GLFW_BUILD_COCOA_TIMER 59 | 60 | -------------------------------------------------------------------------------- /third_party/glfw/src/win32_time.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Win32 - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2002-2006 Marcus Geelnard 5 | // Copyright (c) 2006-2017 Camilla Löwy 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | // Please use C89 style variable declarations in this file because VS 2010 28 | //======================================================================== 29 | 30 | #include "internal.h" 31 | 32 | #if defined(GLFW_BUILD_WIN32_TIMER) 33 | 34 | ////////////////////////////////////////////////////////////////////////// 35 | ////// GLFW platform API ////// 36 | ////////////////////////////////////////////////////////////////////////// 37 | 38 | void _glfwPlatformInitTimer(void) 39 | { 40 | QueryPerformanceFrequency((LARGE_INTEGER*) &_glfw.timer.win32.frequency); 41 | } 42 | 43 | uint64_t _glfwPlatformGetTimerValue(void) 44 | { 45 | uint64_t value; 46 | QueryPerformanceCounter((LARGE_INTEGER*) &value); 47 | return value; 48 | } 49 | 50 | uint64_t _glfwPlatformGetTimerFrequency(void) 51 | { 52 | return _glfw.timer.win32.frequency; 53 | } 54 | 55 | #endif // GLFW_BUILD_WIN32_TIMER 56 | 57 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/window.cpp: -------------------------------------------------------------------------------- 1 | #include "window.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "debug_marker.h" 7 | #include "device.h" 8 | #include "queue.h" 9 | #include "swap_chain.h" 10 | 11 | namespace Pathfinder { 12 | 13 | #ifndef __ANDROID__ 14 | WindowVk::WindowVk(const Vec2I& size, GLFWwindow* window_handle, VkSurfaceKHR surface, VkInstance instance) 15 | : Window(size, window_handle) { 16 | surface_ = surface; 17 | instance_ = instance; 18 | } 19 | #else 20 | WindowVk::WindowVk(const Vec2I& _size, VkSurfaceKHR surface, VkInstance instance) : Window(_size) { 21 | surface_ = surface; 22 | instance_ = instance; 23 | } 24 | #endif 25 | 26 | VkExtent2D WindowVk::choose_swap_extent(const VkSurfaceCapabilitiesKHR& capabilities) const { 27 | if (capabilities.currentExtent.width != UINT32_MAX) { 28 | return capabilities.currentExtent; 29 | } else { 30 | int width, height; 31 | #ifndef __ANDROID__ 32 | 33 | glfwGetFramebufferSize(glfw_window_, &width, &height); 34 | #endif 35 | width = 1000; 36 | height = 1000; 37 | 38 | VkExtent2D actual_extent = {static_cast(width), static_cast(height)}; 39 | 40 | actual_extent.width = std::max(capabilities.minImageExtent.width, 41 | std::min(capabilities.maxImageExtent.width, actual_extent.width)); 42 | actual_extent.height = std::max(capabilities.minImageExtent.height, 43 | std::min(capabilities.maxImageExtent.height, actual_extent.height)); 44 | 45 | return actual_extent; 46 | } 47 | } 48 | 49 | std::shared_ptr WindowVk::get_swap_chain(const std::shared_ptr& device) { 50 | if (!swapchain_) { 51 | auto device_vk = static_cast(device.get()); 52 | swapchain_ = std::make_shared(get_physical_size(), this, device_vk); 53 | } 54 | 55 | return swapchain_; 56 | } 57 | 58 | void WindowVk::destroy() { 59 | #ifndef __ANDROID__ 60 | if (surface_) { 61 | vkDestroySurfaceKHR(instance_, surface_, nullptr); 62 | surface_ = nullptr; 63 | } 64 | 65 | if (glfw_window_) { 66 | glfwDestroyWindow(glfw_window_); 67 | glfw_window_ = nullptr; 68 | } 69 | #endif 70 | } 71 | 72 | } // namespace Pathfinder 73 | -------------------------------------------------------------------------------- /pathfinder/core/paint/paint.cpp: -------------------------------------------------------------------------------- 1 | #include "paint.h" 2 | 3 | namespace Pathfinder { 4 | 5 | RectF rect_to_uv(const RectI &rect, const Vec2F &texture_scale) { 6 | return rect.to_f32() * texture_scale; 7 | } 8 | 9 | bool Paint::is_opaque() const { 10 | if (!base_color.is_opaque()) { 11 | return false; 12 | } 13 | 14 | if (overlay) { 15 | auto &content = overlay->contents; 16 | 17 | if (content.type == PaintContents::Type::Gradient) { 18 | return content.gradient.is_opaque(); 19 | } else { 20 | return content.pattern.is_opaque(); 21 | } 22 | } 23 | 24 | return true; 25 | } 26 | 27 | ColorU Paint::get_base_color() const { 28 | return base_color; 29 | } 30 | 31 | void Paint::set_base_color(const ColorU &color) { 32 | base_color = color; 33 | } 34 | 35 | std::shared_ptr Paint::get_overlay() const { 36 | return overlay; 37 | } 38 | 39 | PaintFilter PaintMetadata::filter() const { 40 | if (!color_texture_metadata) { 41 | return PaintFilter{}; 42 | } 43 | 44 | PaintFilter filter = color_texture_metadata->filter; 45 | 46 | switch (color_texture_metadata->filter.type) { 47 | case PaintFilter::Type::RadialGradient: { 48 | auto uv_rect = rect_to_uv(color_texture_metadata->location.rect, color_texture_metadata->page_scale); 49 | 50 | // Contract rect. 51 | auto amount = Vec2F(0.0, color_texture_metadata->page_scale.y * 0.5f); 52 | uv_rect = RectF(uv_rect.origin() + amount, uv_rect.lower_right() - amount); 53 | 54 | filter.gradient_filter.uv_origin = uv_rect.origin(); 55 | } break; 56 | default: 57 | break; 58 | } 59 | 60 | return filter; 61 | } 62 | 63 | std::shared_ptr PaintMetadata::tile_batch_texture_info() const { 64 | if (color_texture_metadata) { 65 | auto info = std::make_shared(); 66 | info->page_id = color_texture_metadata->location.page; 67 | info->sampling_flags = color_texture_metadata->sampling_flags; 68 | info->composite_op = color_texture_metadata->composite_op; 69 | info->raw_texture = color_texture_metadata->raw_texture; 70 | return info; 71 | } 72 | 73 | return nullptr; 74 | } 75 | 76 | } // namespace Pathfinder 77 | -------------------------------------------------------------------------------- /third_party/glfw/deps/getopt.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, Kim Gräsman 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright notice, 7 | * this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright notice, 9 | * this list of conditions and the following disclaimer in the documentation 10 | * and/or other materials provided with the distribution. 11 | * * Neither the name of Kim Gräsman nor the names of contributors may be used 12 | * to endorse or promote products derived from this software without specific 13 | * prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL KIM GRÄSMAN BE LIABLE FOR ANY DIRECT, 19 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef INCLUDED_GETOPT_PORT_H 28 | #define INCLUDED_GETOPT_PORT_H 29 | 30 | #if defined(__cplusplus) 31 | extern "C" { 32 | #endif 33 | 34 | extern const int no_argument; 35 | extern const int required_argument; 36 | extern const int optional_argument; 37 | 38 | extern char* optarg; 39 | extern int optind, opterr, optopt; 40 | 41 | struct option { 42 | const char* name; 43 | int has_arg; 44 | int* flag; 45 | int val; 46 | }; 47 | 48 | int getopt(int argc, char* const argv[], const char* optstring); 49 | 50 | int getopt_long(int argc, char* const argv[], 51 | const char* optstring, const struct option* longopts, int* longindex); 52 | 53 | #if defined(__cplusplus) 54 | } 55 | #endif 56 | 57 | #endif // INCLUDED_GETOPT_PORT_H 58 | -------------------------------------------------------------------------------- /demo/web/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "../common/app.h" 4 | 5 | #ifdef __EMSCRIPTEN__ 6 | #include 7 | #include 8 | #endif 9 | 10 | constexpr int32_t WINDOW_WIDTH = 640; 11 | constexpr int32_t WINDOW_HEIGHT = 480; 12 | 13 | App* app; 14 | Blit* blit; 15 | 16 | void main_loop(void* p_swap_chain) { 17 | auto* swap_chain = static_cast(p_swap_chain); 18 | 19 | app->update(); 20 | 21 | auto encoder = app->device_->create_command_encoder("main encoder"); 22 | 23 | auto surface_texture = swap_chain->get_surface_texture(); 24 | 25 | // Swap chain render pass. 26 | { 27 | encoder->begin_render_pass(swap_chain->get_render_pass(), 28 | surface_texture, 29 | Pathfinder::ColorF(0.2, 0.2, 0.2, 1.0)); 30 | encoder->set_viewport({{0, 0}, swap_chain->size_}); 31 | 32 | // Draw canvas to screen. 33 | blit->draw(encoder); 34 | 35 | encoder->end_render_pass(); 36 | } 37 | 38 | swap_chain->submit(encoder); 39 | 40 | swap_chain->present(); 41 | } 42 | 43 | int main() { 44 | // Create the primary window. 45 | auto window_builder = 46 | Pathfinder::WindowBuilder::new_impl(Pathfinder::BackendType::Opengl, {WINDOW_WIDTH, WINDOW_HEIGHT}); 47 | auto window = window_builder->get_window(0).lock(); 48 | 49 | // Create device and queue. 50 | auto device = window_builder->request_device(); 51 | auto queue = window_builder->create_queue(); 52 | 53 | // Create swap chains for windows. 54 | auto swap_chain = window->get_swap_chain(device); 55 | 56 | // Create app. 57 | app = new App(device, queue, window->get_physical_size(), {}, {}); 58 | 59 | blit = new Blit(device, queue, swap_chain->get_surface_format()); 60 | 61 | { 62 | const auto dst_texture = 63 | device->create_texture({window->get_physical_size(), Pathfinder::TextureFormat::Rgba8Unorm}, "dst texture"); 64 | 65 | app->canvas_->set_dst_texture(dst_texture); 66 | 67 | blit->set_texture(dst_texture); 68 | } 69 | 70 | emscripten_set_main_loop_arg(main_loop, swap_chain.get(), 0, 1); 71 | 72 | window_builder->stop_and_destroy_swapchains(); 73 | 74 | // Do this after swap chain cleanup. 75 | delete app; 76 | delete blit; 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /pathfinder/core/d3d11/scene_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_D3D11_SCENE_BUILDER_H 2 | #define PATHFINDER_D3D11_SCENE_BUILDER_H 3 | 4 | #include 5 | 6 | #include "../scene_builder.h" 7 | #include "gpu_data.h" 8 | 9 | #ifdef PATHFINDER_ENABLE_D3D11 10 | 11 | namespace Pathfinder { 12 | 13 | struct BuiltSegments { 14 | SegmentsD3D11 draw_segments; 15 | SegmentsD3D11 clip_segments; 16 | 17 | std::vector draw_segment_ranges; 18 | std::vector clip_segment_ranges; 19 | 20 | static BuiltSegments from_scene(const Scene &scene) { 21 | BuiltSegments built_segments; 22 | 23 | built_segments.clip_segment_ranges.reserve(scene.clip_paths.size()); 24 | 25 | for (const auto &clip_path : scene.clip_paths) { 26 | auto range = built_segments.clip_segments.add_path(clip_path.outline); 27 | built_segments.clip_segment_ranges.push_back(range); 28 | } 29 | 30 | built_segments.draw_segment_ranges.reserve(scene.draw_paths.size()); 31 | 32 | for (const auto &draw_path : scene.draw_paths) { 33 | auto range = built_segments.draw_segments.add_path(draw_path.outline); 34 | built_segments.draw_segment_ranges.push_back(range); 35 | } 36 | 37 | return built_segments; 38 | } 39 | }; 40 | 41 | struct ClipBatchesD3D11 { 42 | // Will be submitted in reverse (LIFO) order. 43 | std::vector prepare_batches; 44 | std::unordered_map clip_id_to_path_batch_index; 45 | }; 46 | 47 | class SceneBuilderD3D11 : public SceneBuilder { 48 | public: 49 | SceneBuilderD3D11() = default; 50 | 51 | BuiltSegments built_segments; 52 | 53 | std::shared_ptr clip_batches_d3d11; 54 | 55 | // Will be sent to renderer to draw tiles. 56 | std::vector tile_batches; 57 | 58 | void build(Scene *_scene, Renderer *renderer) override; 59 | 60 | private: 61 | void finish_building(LastSceneInfo &last_scene, 62 | const std::vector &paint_metadata, 63 | const std::shared_ptr> &built_paths); 64 | 65 | void build_tile_batches(LastSceneInfo &last_scene, 66 | const std::vector &paint_metadata, 67 | const std::shared_ptr> &built_paths); 68 | }; 69 | 70 | } // namespace Pathfinder 71 | 72 | #endif 73 | 74 | #endif // PATHFINDER_D3D11_SCENE_BUILDER_H 75 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/shader_module.cpp: -------------------------------------------------------------------------------- 1 | #include "shader_module.h" 2 | 3 | #include 4 | 5 | #include "../../common/global_macros.h" 6 | #include "../../common/logger.h" 7 | #include "base.h" 8 | 9 | namespace Pathfinder { 10 | 11 | bool replace(std::string &str, const std::string &from, const std::string &to) { 12 | size_t start_pos = str.find(from); 13 | if (start_pos == std::string::npos) { 14 | return false; 15 | } 16 | str.replace(start_pos, from.length(), to); 17 | return true; 18 | } 19 | 20 | ShaderModuleGl::ShaderModuleGl(const std::vector &source_code, 21 | ShaderStage shader_stage, 22 | const std::string &label) { 23 | label_ = label; 24 | 25 | switch (shader_stage) { 26 | case ShaderStage::Vertex: { 27 | id_ = glCreateShader(GL_VERTEX_SHADER); 28 | } break; 29 | case ShaderStage::Fragment: { 30 | id_ = glCreateShader(GL_FRAGMENT_SHADER); 31 | } break; 32 | #ifndef __EMSCRIPTEN__ 33 | case ShaderStage::Compute: { 34 | id_ = glCreateShader(GL_COMPUTE_SHADER); 35 | } break; 36 | #endif 37 | default: 38 | abort(); 39 | } 40 | 41 | /// Has to pass string.c_str(), as vector.data() doesn't work. 42 | std::string code_string = {source_code.begin(), source_code.end()}; 43 | 44 | #ifdef PATHFINDER_MINIMUM_SHADER_VERSION_SUPPORT 45 | if (shader_stage == ShaderStage::Compute) { 46 | replace(code_string, "#version 430", "#version 310 es"); 47 | } else { 48 | replace(code_string, "#version 310 es", "#version 300 es"); 49 | } 50 | #endif 51 | 52 | auto code_cstr = code_string.c_str(); 53 | 54 | glShaderSource(id_, 1, &code_cstr, nullptr); 55 | glCompileShader(id_); 56 | 57 | check_compile_errors(); 58 | } 59 | 60 | ShaderModuleGl::~ShaderModuleGl() { 61 | glDeleteShader(id_); 62 | } 63 | 64 | unsigned int ShaderModuleGl::get_handle() const { 65 | return id_; 66 | } 67 | 68 | void ShaderModuleGl::check_compile_errors() const { 69 | GLint success; 70 | glGetShaderiv(id_, GL_COMPILE_STATUS, &success); 71 | 72 | if (!success) { 73 | GLchar info_log[1024]; 74 | glGetShaderInfoLog(id_, 1024, nullptr, info_log); 75 | 76 | std::ostringstream string_stream; 77 | string_stream << "SHADER_COMPILATION_ERROR of : " << label_ << "\n" << info_log; 78 | Logger::error(string_stream.str()); 79 | } 80 | } 81 | 82 | } // namespace Pathfinder 83 | -------------------------------------------------------------------------------- /pathfinder/common/math/mat2.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_MAT2_H 2 | #define PATHFINDER_MAT2_H 3 | 4 | #include "unit_vector.h" 5 | 6 | namespace Pathfinder { 7 | 8 | /// A 2x2 matrix, in column-major order. 9 | struct Mat2 { 10 | float v[4] = {0}; 11 | 12 | Mat2() = default; 13 | 14 | Mat2(float m11, float m21, float m12, float m22) { 15 | v[0] = m11; 16 | v[1] = m21; 17 | v[2] = m12; 18 | v[3] = m22; 19 | } 20 | 21 | static Mat2 identity() { 22 | return Mat2::from_scale(Vec2F(1)); 23 | } 24 | 25 | static Mat2 from_scale(Vec2F scale) { 26 | return {scale.x, 0.0, 0.0, scale.y}; 27 | } 28 | 29 | static Mat2 from_rotation(float theta) { 30 | return Mat2::from_rotation_vector(UnitVector::from_angle(theta)); 31 | } 32 | 33 | static Mat2 from_rotation_vector(const UnitVector &vector) { 34 | return {1.0f * vector.x, 1.0f * vector.y, -1.0f * vector.y, 1.0f * vector.x}; 35 | } 36 | 37 | float det() const { 38 | return v[0] * v[3] - v[1] * v[2]; 39 | } 40 | 41 | Mat2 adjugate() const { 42 | return {v[3] * 1.0f, v[1] * -1.0f, v[2] * -1.0f, v[0] * 1.0f}; 43 | } 44 | 45 | Mat2 inverse() const { 46 | return adjugate() * (1.0f / det()); 47 | } 48 | 49 | float m11() const { 50 | return v[0]; 51 | } 52 | 53 | float m21() const { 54 | return v[1]; 55 | } 56 | 57 | float m12() const { 58 | return v[2]; 59 | } 60 | 61 | float m22() const { 62 | return v[3]; 63 | } 64 | 65 | Mat2 operator*(float s) const { 66 | return {v[0] * s, v[1] * s, v[2] * s, v[3] * s}; 67 | } 68 | 69 | Mat2 operator*(const Mat2 &other) const { 70 | return {v[0] * other.v[0] + v[2] * other.v[1], 71 | v[1] * other.v[0] + v[3] * other.v[1], 72 | v[0] * other.v[2] + v[2] * other.v[3], 73 | v[1] * other.v[2] + v[3] * other.v[3]}; 74 | } 75 | 76 | bool operator==(const Mat2 &b) const { 77 | return v[0] == b.v[0] && v[1] == b.v[1] && v[2] == b.v[2] && v[3] == b.v[3]; 78 | } 79 | 80 | // For being used as ordered key. 81 | bool operator<(const Mat2 &b) const { 82 | return v[0] < b.v[0] && v[1] < b.v[1] && v[2] < b.v[2] && v[3] < b.v[3]; 83 | } 84 | 85 | Vec2F operator*(const Vec2F &other) const { 86 | return {v[0] * other.x + v[2] * other.y, v[1] * other.x + v[3] * other.y}; 87 | } 88 | }; 89 | 90 | } // namespace Pathfinder 91 | 92 | #endif // PATHFINDER_MAT2_H 93 | -------------------------------------------------------------------------------- /third_party/glfw/src/linux_joystick.h: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 Linux - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2014 Jonas Ådahl 5 | // 6 | // This software is provided 'as-is', without any express or implied 7 | // warranty. In no event will the authors be held liable for any damages 8 | // arising from the use of this software. 9 | // 10 | // Permission is granted to anyone to use this software for any purpose, 11 | // including commercial applications, and to alter it and redistribute it 12 | // freely, subject to the following restrictions: 13 | // 14 | // 1. The origin of this software must not be misrepresented; you must not 15 | // claim that you wrote the original software. If you use this software 16 | // in a product, an acknowledgment in the product documentation would 17 | // be appreciated but is not required. 18 | // 19 | // 2. Altered source versions must be plainly marked as such, and must not 20 | // be misrepresented as being the original software. 21 | // 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | // 25 | //======================================================================== 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #define GLFW_LINUX_JOYSTICK_STATE _GLFWjoystickLinux linjs; 32 | #define GLFW_LINUX_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs; 33 | 34 | // Linux-specific joystick data 35 | // 36 | typedef struct _GLFWjoystickLinux 37 | { 38 | int fd; 39 | char path[PATH_MAX]; 40 | int keyMap[KEY_CNT - BTN_MISC]; 41 | int absMap[ABS_CNT]; 42 | struct input_absinfo absInfo[ABS_CNT]; 43 | int hats[4][2]; 44 | } _GLFWjoystickLinux; 45 | 46 | // Linux-specific joystick API data 47 | // 48 | typedef struct _GLFWlibraryLinux 49 | { 50 | int inotify; 51 | int watch; 52 | regex_t regex; 53 | GLFWbool dropped; 54 | } _GLFWlibraryLinux; 55 | 56 | void _glfwDetectJoystickConnectionLinux(void); 57 | 58 | GLFWbool _glfwInitJoysticksLinux(void); 59 | void _glfwTerminateJoysticksLinux(void); 60 | GLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode); 61 | const char* _glfwGetMappingNameLinux(void); 62 | void _glfwUpdateGamepadGUIDLinux(char* guid); 63 | 64 | -------------------------------------------------------------------------------- /pathfinder/common/i32x4.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_I32X4_H 2 | #define PATHFINDER_I32X4_H 3 | 4 | #include 5 | 6 | #include "global_macros.h" 7 | 8 | #ifdef __ANDROID__ 9 | // A C/C++ header file that converts Intel SSE intrinsics to Arm/Aarch64 NEON intrinsics. 10 | #include 11 | #else 12 | #include 13 | #include 14 | // #include // Required by AVX2, which we won't be using due its absence on ARM. 15 | #endif 16 | 17 | namespace Pathfinder { 18 | 19 | /// Four 32-bit ints (SIMD). 20 | struct I32x4 { 21 | __m128i v = _mm_setzero_si128(); 22 | 23 | I32x4() = default; 24 | 25 | explicit I32x4(__m128i _v) : v(_v) {} 26 | 27 | I32x4(int32_t x, int32_t y, int32_t z, int32_t w) { 28 | v = _mm_setr_epi32(x, y, z, w); 29 | } 30 | 31 | inline static I32x4 splat(int32_t x) { 32 | return I32x4(_mm_set1_epi32(x)); 33 | } 34 | 35 | inline I32x4 shift_l(int32_t count) const { 36 | // Same as _mm_sllv_epi32(v, _mm_set1_epi32(count)), but that requires AVX2. 37 | // Cf. https://stackoverflow.com/questions/14731442/am-i-using-mm-srl-epi32-wrong 38 | return I32x4(_mm_sll_epi32(v, _mm_set_epi32(0, 0, 0, count))); 39 | } 40 | 41 | inline I32x4 shift_r(int32_t count) const { 42 | // Same as _mm_srlv_epi32(v, _mm_set1_epi32(count)), but that requires AVX2. 43 | // Cf. https://stackoverflow.com/questions/14731442/am-i-using-mm-srl-epi32-wrong 44 | return I32x4(_mm_srl_epi32(v, _mm_set_epi32(0, 0, 0, count))); 45 | } 46 | 47 | inline I32x4 operator+(const I32x4 &b) const { 48 | return I32x4(_mm_add_epi32(v, b.v)); 49 | } 50 | 51 | inline I32x4 operator-(const I32x4 &b) const { 52 | return I32x4(_mm_sub_epi32(v, b.v)); 53 | } 54 | 55 | inline I32x4 operator*(const I32x4 &b) const { 56 | // Multiply 2 and 0. 57 | __m128i tmp1 = _mm_mul_epu32(v, b.v); 58 | // Multiply 3 and 1. 59 | __m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(v, 4), _mm_srli_si128(b.v, 4)); 60 | // Shuffle results to [63..0] and pack. 61 | // 8 = _MM_SHUFFLE(0, 0, 2, 0) 62 | return I32x4(_mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, 8), _mm_shuffle_epi32(tmp2, 8))); 63 | } 64 | 65 | inline void operator+=(const I32x4 &b) { 66 | *this = *this + b; 67 | } 68 | 69 | inline void operator-=(const I32x4 &b) { 70 | *this = *this - b; 71 | } 72 | }; 73 | 74 | } // namespace Pathfinder 75 | 76 | #endif // PATHFINDER_I32X4_H 77 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/framebuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "framebuffer.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "debug_marker.h" 7 | 8 | namespace Pathfinder { 9 | 10 | FramebufferVk::FramebufferVk(VkDevice vk_device, VkRenderPass vk_render_pass, const std::shared_ptr &texture) 11 | : Framebuffer(texture) { 12 | vk_device_ = vk_device; 13 | 14 | auto texture_vk = static_cast(texture.get()); 15 | 16 | std::array attachments = {texture_vk->get_image_view()}; 17 | 18 | VkFramebufferCreateInfo framebufferInfo{}; 19 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 20 | framebufferInfo.renderPass = vk_render_pass; 21 | framebufferInfo.attachmentCount = static_cast(attachments.size()); 22 | framebufferInfo.pAttachments = attachments.data(); 23 | framebufferInfo.width = texture->get_size().x; 24 | framebufferInfo.height = texture->get_size().y; 25 | framebufferInfo.layers = 1; 26 | 27 | VK_CHECK_RESULT(vkCreateFramebuffer(vk_device, &framebufferInfo, nullptr, &vk_framebuffer_)) 28 | } 29 | 30 | FramebufferVk::FramebufferVk(VkDevice vk_device, VkRenderPass vk_render_pass, Vec2I size, VkImageView vk_image_view) { 31 | vk_device_ = vk_device; 32 | label_ = "Swapchain framebuffer"; 33 | 34 | std::array attachments = {vk_image_view}; 35 | 36 | VkFramebufferCreateInfo framebufferInfo{}; 37 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 38 | framebufferInfo.renderPass = vk_render_pass; 39 | framebufferInfo.attachmentCount = static_cast(attachments.size()); 40 | framebufferInfo.pAttachments = attachments.data(); 41 | framebufferInfo.width = size.x; 42 | framebufferInfo.height = size.y; 43 | framebufferInfo.layers = 1; 44 | 45 | VK_CHECK_RESULT(vkCreateFramebuffer(vk_device, &framebufferInfo, nullptr, &vk_framebuffer_)) 46 | } 47 | 48 | FramebufferVk::~FramebufferVk() { 49 | vkDestroyFramebuffer(vk_device_, vk_framebuffer_, nullptr); 50 | } 51 | 52 | VkFramebuffer FramebufferVk::get_vk_handle() const { 53 | return vk_framebuffer_; 54 | } 55 | 56 | void FramebufferVk::set_label(const std::string &label) { 57 | Framebuffer::set_label(label); 58 | 59 | DebugMarker::get_singleton()->set_object_name(vk_device_, 60 | (uint64_t)vk_framebuffer_, 61 | VK_OBJECT_TYPE_FRAMEBUFFER, 62 | label); 63 | } 64 | 65 | } // namespace Pathfinder 66 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/program.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_PROGRAM_H 2 | #define PATHFINDER_GPU_PROGRAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../../common/global_macros.h" 11 | #include "../../common/logger.h" 12 | #include "../../common/math/mat2.h" 13 | #include "../../common/math/mat4.h" 14 | #include "base.h" 15 | 16 | namespace Pathfinder { 17 | 18 | class ShaderModule; 19 | 20 | class Program { 21 | public: 22 | /// Activate the shader. 23 | void use() const; 24 | 25 | unsigned int get_handle() const; 26 | 27 | // Utility uniform functions. 28 | // ------------------------------------------------------ 29 | void set_bool(const std::string &name, bool value) const; 30 | 31 | void set_int(const std::string &name, int value) const; 32 | 33 | void set_float(const std::string &name, float value) const; 34 | 35 | void set_vec2(const std::string &name, float x, float y) const; 36 | 37 | void set_vec2i(const std::string &name, int x, int y) const; 38 | 39 | void set_vec3(const std::string &name, float x, float y, float z) const; 40 | 41 | void set_vec4(const std::string &name, float x, float y, float z, float w) const; 42 | 43 | void set_mat2(const std::string &name, const Mat2 &mat) const; 44 | 45 | void set_mat4(const std::string &name, const Mat4 &mat) const; 46 | // ------------------------------------------------------ 47 | 48 | protected: 49 | /// Program ID. 50 | unsigned int id_{}; 51 | 52 | /// Utility function for checking shader linking errors. 53 | void check_compile_errors() const { 54 | GLint success; 55 | glGetProgramiv(id_, GL_LINK_STATUS, &success); 56 | 57 | if (!success) { 58 | GLchar info_log[1024]; 59 | glGetProgramInfoLog(id_, 1024, nullptr, info_log); 60 | 61 | std::ostringstream string_stream; 62 | string_stream << "PROGRAM_LINKING_ERROR:" 63 | << "\n" 64 | << info_log; 65 | Logger::error(string_stream.str()); 66 | } 67 | } 68 | }; 69 | 70 | class RasterProgram : public Program { 71 | public: 72 | RasterProgram(const std::shared_ptr &vertex_shader_module, 73 | const std::shared_ptr &fragment_shader_module); 74 | }; 75 | 76 | class ComputeProgram : public Program { 77 | public: 78 | explicit ComputeProgram(const std::shared_ptr &compute_shader_module); 79 | }; 80 | 81 | } // namespace Pathfinder 82 | 83 | #endif // PATHFINDER_GPU_PROGRAM_H 84 | -------------------------------------------------------------------------------- /third_party/glfw/src/posix_time.c: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | // GLFW 3.4 POSIX - www.glfw.org 3 | //------------------------------------------------------------------------ 4 | // Copyright (c) 2002-2006 Marcus Geelnard 5 | // Copyright (c) 2006-2017 Camilla Löwy 6 | // 7 | // This software is provided 'as-is', without any express or implied 8 | // warranty. In no event will the authors be held liable for any damages 9 | // arising from the use of this software. 10 | // 11 | // Permission is granted to anyone to use this software for any purpose, 12 | // including commercial applications, and to alter it and redistribute it 13 | // freely, subject to the following restrictions: 14 | // 15 | // 1. The origin of this software must not be misrepresented; you must not 16 | // claim that you wrote the original software. If you use this software 17 | // in a product, an acknowledgment in the product documentation would 18 | // be appreciated but is not required. 19 | // 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 23 | // 3. This notice may not be removed or altered from any source 24 | // distribution. 25 | // 26 | //======================================================================== 27 | // It is fine to use C99 in this file because it will not be built with VS 28 | //======================================================================== 29 | 30 | #include "internal.h" 31 | 32 | #if defined(GLFW_BUILD_POSIX_TIMER) 33 | 34 | #include 35 | #include 36 | 37 | 38 | ////////////////////////////////////////////////////////////////////////// 39 | ////// GLFW platform API ////// 40 | ////////////////////////////////////////////////////////////////////////// 41 | 42 | void _glfwPlatformInitTimer(void) 43 | { 44 | _glfw.timer.posix.clock = CLOCK_REALTIME; 45 | _glfw.timer.posix.frequency = 1000000000; 46 | 47 | #if defined(_POSIX_MONOTONIC_CLOCK) 48 | struct timespec ts; 49 | if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 50 | _glfw.timer.posix.clock = CLOCK_MONOTONIC; 51 | #endif 52 | } 53 | 54 | uint64_t _glfwPlatformGetTimerValue(void) 55 | { 56 | struct timespec ts; 57 | clock_gettime(_glfw.timer.posix.clock, &ts); 58 | return (uint64_t) ts.tv_sec * _glfw.timer.posix.frequency + (uint64_t) ts.tv_nsec; 59 | } 60 | 61 | uint64_t _glfwPlatformGetTimerFrequency(void) 62 | { 63 | return _glfw.timer.posix.frequency; 64 | } 65 | 66 | #endif // GLFW_BUILD_POSIX_TIMER 67 | 68 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d11/bound.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | // Initializes the tile maps. 4 | 5 | precision highp float; 6 | 7 | #define TILE_FIELD_NEXT_TILE_ID 0u 8 | #define TILE_FIELD_FIRST_FILL_ID 1u 9 | #define TILE_FIELD_BACKDROP_ALPHA_TILE_ID 2u 10 | #define TILE_FIELD_CONTROL 3u 11 | 12 | layout(local_size_x = 64) in; 13 | 14 | layout(std140, binding = 2) uniform bUniform { 15 | int uPathCount; 16 | int uTileCount; 17 | int uPad0; 18 | int uPad1; 19 | }; 20 | 21 | restrict readonly layout(std430, binding = 0) buffer bTilePathInfo { 22 | // x: tile upper left, 16-bit packed x/y 23 | // y: tile lower right, 16-bit packed x/y 24 | // z: first tile index in this path 25 | // w: color/ctrl/backdrop word 26 | uvec4 iTilePathInfo[]; 27 | }; 28 | 29 | restrict writeonly layout(std430, binding = 1) buffer bTiles { 30 | // [0]: next tile ID (initialized to -1) 31 | // [1]: first fill ID (initialized to -1) 32 | // [2]: backdrop delta upper 8 bits, alpha tile ID lower 24 (initialized to 0, -1 respectively) 33 | // [3]: color/ctrl/backdrop word 34 | uint iTiles[]; 35 | }; 36 | 37 | void main() { 38 | uint tileIndex = gl_GlobalInvocationID.x; 39 | if (tileIndex >= uint(uTileCount)) return; 40 | 41 | uint lowPathIndex = 0u, highPathIndex = uint(uPathCount); 42 | int iteration = 0; 43 | while (iteration < 1024 && lowPathIndex + 1u < highPathIndex) { 44 | uint midPathIndex = lowPathIndex + (highPathIndex - lowPathIndex) / 2u; 45 | uint midTileIndex = iTilePathInfo[midPathIndex].z; 46 | if (tileIndex < midTileIndex) { 47 | highPathIndex = midPathIndex; 48 | } else { 49 | lowPathIndex = midPathIndex; 50 | if (tileIndex == midTileIndex) break; 51 | } 52 | iteration++; 53 | } 54 | 55 | uint pathIndex = lowPathIndex; 56 | uvec4 pathInfo = iTilePathInfo[pathIndex]; 57 | 58 | ivec2 packedTileRect = ivec2(pathInfo.xy); 59 | ivec4 tileRect = ivec4( 60 | (packedTileRect.x << 16) >> 16, 61 | packedTileRect.x >> 16, 62 | (packedTileRect.y << 16) >> 16, 63 | packedTileRect.y >> 16); 64 | 65 | uint tileOffset = tileIndex - pathInfo.z; 66 | uint tileWidth = uint(tileRect.z - tileRect.x); 67 | ivec2 tileCoords = tileRect.xy + ivec2(tileOffset % tileWidth, tileOffset / tileWidth); 68 | 69 | iTiles[tileIndex * 4u + TILE_FIELD_NEXT_TILE_ID] = ~0u; 70 | iTiles[tileIndex * 4u + TILE_FIELD_FIRST_FILL_ID] = ~0u; 71 | iTiles[tileIndex * 4u + TILE_FIELD_BACKDROP_ALPHA_TILE_ID] = 0x00ffffffu; 72 | iTiles[tileIndex * 4u + TILE_FIELD_CONTROL] = pathInfo.w; 73 | } 74 | -------------------------------------------------------------------------------- /pathfinder/shaders/generated/tile_clip_combine_frag_spv.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_RESOURCE_TILE_CLIP_COMBINE_FRAG_SPV_H 2 | #define PATHFINDER_RESOURCE_TILE_CLIP_COMBINE_FRAG_SPV_H 3 | 4 | namespace Pathfinder { 5 | static uint8_t tile_clip_combine_frag_spv[] = {3,2,35,7,0,0,1,0,11,0,13,0,36,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,10,0,4,0,0,0,4,0,0,0,109,97,105,110,0,0,0,0,9,0,0,0,17,0,0,0,21,0,0,0,27,0,0,0,30,0,0,0,16,0,3,0,4,0,0,0,7,0,0,0,3,0,3,0,1,0,0,0,54,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5,0,5,0,9,0,0,0,111,70,114,97,103,67,111,108,111,114,0,0,5,0,4,0,13,0,0,0,117,83,114,99,0,0,0,0,5,0,5,0,17,0,0,0,118,84,101,120,67,111,111,114,100,48,0,0,5,0,5,0,21,0,0,0,118,66,97,99,107,100,114,111,112,48,0,0,5,0,5,0,27,0,0,0,118,84,101,120,67,111,111,114,100,49,0,0,5,0,5,0,30,0,0,0,118,66,97,99,107,100,114,111,112,49,0,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,34,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,33,0,0,0,1,0,0,0,71,0,4,0,17,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,21,0,0,0,30,0,0,0,1,0,0,0,71,0,4,0,27,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,30,0,0,0,30,0,0,0,3,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,25,0,9,0,10,0,0,0,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,11,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,0,0,0,0,11,0,0,0,59,0,4,0,12,0,0,0,13,0,0,0,0,0,0,0,23,0,4,0,15,0,0,0,6,0,0,0,2,0,0,0,32,0,4,0,16,0,0,0,1,0,0,0,15,0,0,0,59,0,4,0,16,0,0,0,17,0,0,0,1,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,6,0,0,0,59,0,4,0,20,0,0,0,21,0,0,0,1,0,0,0,59,0,4,0,16,0,0,0,27,0,0,0,1,0,0,0,59,0,4,0,20,0,0,0,30,0,0,0,1,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,61,0,4,0,11,0,0,0,14,0,0,0,13,0,0,0,61,0,4,0,15,0,0,0,18,0,0,0,17,0,0,0,87,0,5,0,7,0,0,0,19,0,0,0,14,0,0,0,18,0,0,0,61,0,4,0,6,0,0,0,22,0,0,0,21,0,0,0,80,0,7,0,7,0,0,0,23,0,0,0,22,0,0,0,22,0,0,0,22,0,0,0,22,0,0,0,129,0,5,0,7,0,0,0,24,0,0,0,19,0,0,0,23,0,0,0,12,0,6,0,7,0,0,0,25,0,0,0,1,0,0,0,4,0,0,0,24,0,0,0,61,0,4,0,11,0,0,0,26,0,0,0,13,0,0,0,61,0,4,0,15,0,0,0,28,0,0,0,27,0,0,0,87,0,5,0,7,0,0,0,29,0,0,0,26,0,0,0,28,0,0,0,61,0,4,0,6,0,0,0,31,0,0,0,30,0,0,0,80,0,7,0,7,0,0,0,32,0,0,0,31,0,0,0,31,0,0,0,31,0,0,0,31,0,0,0,129,0,5,0,7,0,0,0,33,0,0,0,29,0,0,0,32,0,0,0,12,0,6,0,7,0,0,0,34,0,0,0,1,0,0,0,4,0,0,0,33,0,0,0,12,0,7,0,7,0,0,0,35,0,0,0,1,0,0,0,37,0,0,0,25,0,0,0,34,0,0,0,62,0,3,0,9,0,0,0,35,0,0,0,253,0,1,0,56,0,1,0}; 6 | } 7 | 8 | #endif //PATHFINDER_RESOURCE_TILE_CLIP_COMBINE_FRAG_SPV_H 9 | -------------------------------------------------------------------------------- /pathfinder/gpu/vk/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "debug_marker.h" 7 | #include "device.h" 8 | 9 | namespace Pathfinder { 10 | 11 | BufferVk::BufferVk(VkDevice vk_device, const BufferDescriptor& desc) : Buffer(desc), vk_device_(vk_device) {} 12 | 13 | BufferVk::~BufferVk() { 14 | vkDestroyBuffer(vk_device_, vk_buffer_, nullptr); 15 | vkFreeMemory(vk_device_, vk_device_memory_, nullptr); 16 | 17 | if (vk_staging_buffer_) { 18 | vkDestroyBuffer(vk_device_, vk_staging_buffer_, nullptr); 19 | vkFreeMemory(vk_device_, vk_staging_device_memory_, nullptr); 20 | } 21 | } 22 | 23 | VkBuffer BufferVk::get_vk_buffer() { 24 | return vk_buffer_; 25 | } 26 | 27 | VkDeviceMemory BufferVk::get_vk_device_memory() { 28 | return vk_device_memory_; 29 | } 30 | 31 | void BufferVk::upload_via_mapping(size_t data_size, size_t offset, const void* data) { 32 | if (desc_.property != MemoryProperty::HostVisibleAndCoherent) { 33 | abort(); 34 | } 35 | 36 | void* mapped_data; 37 | auto res = vkMapMemory(vk_device_, vk_device_memory_, offset, data_size, 0, &mapped_data); 38 | 39 | if (res != VK_SUCCESS) { 40 | Logger::error("Failed to map memory!"); 41 | return; 42 | } 43 | 44 | memcpy(mapped_data, data, data_size); 45 | vkUnmapMemory(vk_device_, vk_device_memory_); 46 | } 47 | 48 | void BufferVk::download_via_mapping(size_t data_size, size_t offset, void* data) { 49 | if (desc_.property != MemoryProperty::HostVisibleAndCoherent) { 50 | abort(); 51 | } 52 | 53 | void* mapped_data; 54 | auto res = vkMapMemory(vk_device_, vk_device_memory_, offset, data_size, 0, &mapped_data); 55 | 56 | if (res != VK_SUCCESS) { 57 | Logger::error("Failed to map memory!"); 58 | return; 59 | } 60 | 61 | memcpy(data, mapped_data, data_size); 62 | vkUnmapMemory(vk_device_, vk_device_memory_); 63 | } 64 | 65 | void BufferVk::set_label(const std::string& label) { 66 | assert(vk_device_ != nullptr && vk_buffer_ != nullptr); 67 | 68 | Buffer::set_label(label); 69 | 70 | DebugMarker::get_singleton()->set_object_name(vk_device_, (uint64_t)vk_buffer_, VK_OBJECT_TYPE_BUFFER, label); 71 | } 72 | 73 | void BufferVk::create_staging_buffer(DeviceVk* device_vk) { 74 | if (vk_staging_buffer_ != VK_NULL_HANDLE) { 75 | return; 76 | } 77 | 78 | device_vk->create_vk_buffer(get_size(), 79 | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, 80 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 81 | vk_staging_buffer_, 82 | vk_staging_device_memory_); 83 | } 84 | 85 | } // namespace Pathfinder 86 | -------------------------------------------------------------------------------- /pathfinder/shaders/d3d11/sort.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | precision highp float; 4 | 5 | #define TILE_FIELD_NEXT_TILE_ID 0 6 | #define TILE_FIELD_FIRST_FILL_ID 1 7 | #define TILE_FIELD_BACKDROP_ALPHA_TILE_ID 2 8 | #define TILE_FIELD_CONTROL 3 9 | 10 | #define FILL_INDIRECT_DRAW_PARAMS_SIZE 8 11 | 12 | layout(std140, binding = 3) uniform bUniform { 13 | int uTileCount; 14 | int uPad0; 15 | int uPad1; 16 | int uPad2; 17 | }; 18 | 19 | restrict layout(std430, binding = 0) buffer bTiles { 20 | // [0]: next tile ID 21 | // [1]: first fill ID 22 | // [2]: backdrop delta upper 8 bits, alpha tile ID lower 24 23 | // [3]: color/ctrl/backdrop word 24 | uint iTiles[]; 25 | }; 26 | 27 | restrict layout(std430, binding = 1) buffer bFirstTileMap { 28 | int iFirstTileMap[]; 29 | }; 30 | 31 | restrict readonly layout(std430, binding = 2) buffer bZBuffer { 32 | int iZBuffer[]; 33 | }; 34 | 35 | layout(local_size_x = 64) in; 36 | 37 | int getFirst(uint globalTileIndex) { 38 | return iFirstTileMap[globalTileIndex]; 39 | } 40 | 41 | int getNextTile(int tileIndex) { 42 | return int(iTiles[tileIndex * 4 + TILE_FIELD_NEXT_TILE_ID]); 43 | } 44 | 45 | void setNextTile(int tileIndex, int newNextTileIndex) { 46 | iTiles[tileIndex * 4 + TILE_FIELD_NEXT_TILE_ID] = uint(newNextTileIndex); 47 | } 48 | 49 | void main() { 50 | uint globalTileIndex = gl_GlobalInvocationID.x; 51 | if (globalTileIndex >= uint(uTileCount)) return; 52 | 53 | int zValue = iZBuffer[FILL_INDIRECT_DRAW_PARAMS_SIZE + int(globalTileIndex)]; 54 | 55 | int unsortedFirstTileIndex = getFirst(globalTileIndex); 56 | int sortedFirstTileIndex = -1; 57 | 58 | while (unsortedFirstTileIndex >= 0) { 59 | int currentTileIndex = unsortedFirstTileIndex; 60 | unsortedFirstTileIndex = getNextTile(currentTileIndex); 61 | 62 | if (currentTileIndex >= zValue) { 63 | int prevTrialTileIndex = -1; 64 | int trialTileIndex = sortedFirstTileIndex; 65 | while (true) { 66 | if (trialTileIndex < 0 || currentTileIndex < trialTileIndex) { 67 | if (prevTrialTileIndex < 0) { 68 | setNextTile(currentTileIndex, sortedFirstTileIndex); 69 | sortedFirstTileIndex = currentTileIndex; 70 | } else { 71 | setNextTile(currentTileIndex, trialTileIndex); 72 | setNextTile(prevTrialTileIndex, currentTileIndex); 73 | } 74 | break; 75 | } 76 | prevTrialTileIndex = trialTileIndex; 77 | trialTileIndex = getNextTile(trialTileIndex); 78 | } 79 | } 80 | } 81 | 82 | iFirstTileMap[globalTileIndex] = sortedFirstTileIndex; 83 | } 84 | -------------------------------------------------------------------------------- /pathfinder/gpu/gl/debug_marker.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_GPU_GL_DEBUG_MARKER_H 2 | #define PATHFINDER_GPU_GL_DEBUG_MARKER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../../common/global_macros.h" 8 | #include "../../common/logger.h" 9 | #include "base.h" 10 | 11 | namespace Pathfinder { 12 | 13 | struct DebugMarker { 14 | static void label_buffer(GLuint object, const std::string &label) { 15 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 16 | if (GLAD_GL_EXT_debug_label) { 17 | glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, object, 0, label.c_str()); 18 | } 19 | #endif 20 | } 21 | 22 | static void label_shader(GLuint object, const std::string &label) { 23 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 24 | if (GLAD_GL_EXT_debug_label) { 25 | glLabelObjectEXT(GL_SHADER_OBJECT_EXT, object, 0, label.c_str()); 26 | } 27 | #endif 28 | } 29 | 30 | static void label_program(GLuint object, const std::string &label) { 31 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 32 | if (GLAD_GL_EXT_debug_label) { 33 | glLabelObjectEXT(GL_PROGRAM_OBJECT_EXT, object, 0, label.c_str()); 34 | } 35 | #endif 36 | } 37 | 38 | static void label_vao(GLuint object, const std::string &label) { 39 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 40 | if (GLAD_GL_EXT_debug_label) { 41 | glLabelObjectEXT(GL_VERTEX_ARRAY_OBJECT_EXT, object, 0, label.c_str()); 42 | } 43 | #endif 44 | } 45 | 46 | static void label_texture(GLuint object, const std::string &label) { 47 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 48 | if (GLAD_GL_EXT_debug_label) { 49 | glLabelObjectEXT(GL_TEXTURE, object, 0, label.c_str()); 50 | } 51 | #endif 52 | } 53 | 54 | static void label_framebuffer(GLuint object, const std::string &label) { 55 | #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) 56 | if (GLAD_GL_EXT_debug_label) { 57 | glLabelObjectEXT(GL_FRAMEBUFFER, object, 0, label.c_str()); 58 | } 59 | #endif 60 | } 61 | }; 62 | 63 | inline void gl_check_error(const char *flag) { 64 | #ifdef PATHFINDER_DEBUG 65 | for (GLint error = glGetError(); error; error = glGetError()) { 66 | std::ostringstream string_stream; 67 | string_stream << "Error " << error << " after " << flag; 68 | Logger::error(string_stream.str()); 69 | } 70 | #endif 71 | } 72 | 73 | inline void gl_print_string(const char *name, GLenum s) { 74 | #ifdef PATHFINDER_DEBUG 75 | const char *v = (const char *)glGetString(s); 76 | 77 | std::ostringstream string_stream; 78 | string_stream << "GL " << name << " = " << v; 79 | 80 | Logger::error(string_stream.str()); 81 | #endif 82 | } 83 | 84 | } // namespace Pathfinder 85 | 86 | #endif // PATHFINDER_GPU_GL_DEBUG_MARKER_H 87 | -------------------------------------------------------------------------------- /pathfinder/common/math/basic.h: -------------------------------------------------------------------------------- 1 | #ifndef PATHFINDER_BASIC_MATH_H 2 | #define PATHFINDER_BASIC_MATH_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../logger.h" 8 | 9 | namespace Pathfinder { 10 | 11 | // To handle floating point error. 12 | constexpr float FLOAT_EPSILON = 0.0001; 13 | 14 | constexpr float PI = 3.141592653589f; 15 | 16 | /// Convert degree to radian. 17 | inline float deg2rad(float x) { 18 | return x * (PI / 180.0f); 19 | } 20 | 21 | /// Convert radian to degree. 22 | inline float rad2deg(float x) { 23 | return x * (180.0f / PI); 24 | } 25 | 26 | /// Get the upper 2^x of value v. 27 | inline unsigned long upper_power_of_two(unsigned long v) { 28 | if (v == 0) { 29 | return 0; 30 | } 31 | 32 | v--; 33 | v |= v >> 1; 34 | v |= v >> 2; 35 | v |= v >> 4; 36 | v |= v >> 8; 37 | v |= v >> 16; 38 | v++; 39 | 40 | return v; 41 | } 42 | 43 | template 44 | T clamp(T value, T min, T max) { 45 | return value < min ? min : (value > max ? max : value); 46 | } 47 | 48 | inline float lerp(float current, float target, float t) { 49 | assert(t >= 0 && t <= 1); 50 | t = clamp(t, 0.0f, 1.0f); 51 | return current + (target - current) * t; 52 | } 53 | 54 | inline int alignup_i32(int32_t a, int32_t b) { 55 | return (a + b - 1) / b; 56 | } 57 | 58 | static uint64_t fnv_hash(const char* bytes, size_t size) { 59 | const unsigned int fnv_prime = 0x811C9DC5; 60 | uint64_t hash = 0; 61 | 62 | for (uint32_t i = 0; i < size; i++) { 63 | hash *= fnv_prime; 64 | hash ^= (bytes[i]); 65 | } 66 | 67 | return hash; 68 | } 69 | 70 | struct Range { 71 | /// The lower bound of the range (inclusive). 72 | unsigned long long start = 0; 73 | 74 | /// The upper bound of the range (exclusive). 75 | unsigned long long end = 0; 76 | 77 | Range() = default; 78 | 79 | Range(unsigned long long start, unsigned long long end) : start(start), end(end) {}; 80 | 81 | unsigned long long length() const { 82 | // Detect implicit conversion into zero of possible negative lengths. 83 | if (end < start) { 84 | Logger::error("Expects END < START in a Range!"); 85 | } 86 | 87 | return end - start; 88 | } 89 | }; 90 | 91 | // Rounding up to the nearest multiple of a number. 92 | inline int round_up(int number, int multiple) { 93 | if (multiple == 0) { 94 | return number; 95 | } 96 | 97 | int remainder = abs(number) % multiple; 98 | if (remainder == 0) { 99 | return number; 100 | } 101 | 102 | if (number < 0) { 103 | return -(abs(number) - remainder); 104 | } 105 | 106 | return number + multiple - remainder; 107 | } 108 | 109 | } // namespace Pathfinder 110 | 111 | #endif // PATHFINDER_BASIC_MATH_H 112 | --------------------------------------------------------------------------------