diff --git a/cmake/RiveThirdParty.cmake b/cmake/RiveThirdParty.cmake index 494d1a1..65e9009 100644 --- a/cmake/RiveThirdParty.cmake +++ b/cmake/RiveThirdParty.cmake @@ -349,6 +349,8 @@ file(GLOB RIVE_GLAD_SOURCES CONFIGURE_DEPENDS ) list(FILTER RIVE_RENDERER_SOURCES EXCLUDE REGEX "/webgpu/") +list(FILTER RIVE_RENDERER_SOURCES EXCLUDE REGEX "/ore/(d3d11|d3d12|gl|vulkan|wgpu)/") +list(FILTER RIVE_RENDERER_OBJCXX_SOURCES EXCLUDE REGEX "/ore/(gl|metal)/") if(NOT RIVEQT_ENABLE_OPENGL) list(FILTER RIVE_RENDERER_SOURCES EXCLUDE REGEX "/gl/") endif() diff --git a/cmake/generate_rive_shaders.py b/cmake/generate_rive_shaders.py index 1938228..0b3d83a 100644 --- a/cmake/generate_rive_shaders.py +++ b/cmake/generate_rive_shaders.py @@ -14,11 +14,17 @@ "draw_clockwise_path.main", "draw_clockwise_clip.main", "draw_clockwise_interior_triangles.main", - "draw_clockwise_interior_triangles_clip.main", + "draw_clockwise_clip_interior_triangles.main", "draw_clockwise_atlas_blit.main", "draw_clockwise_image_mesh.main", + "draw_clockwise_atomic_path.main", + "draw_clockwise_atomic_interior_triangles.main", "draw_clockwise_atomic_atlas_blit.main", "draw_clockwise_atomic_image_mesh.main", + "init_clockwise_atomic_workaround.frag", + "draw_clockwise_atomic_clip.frag", + "draw_clockwise_atomic_clip_interior_triangles.frag", + "clear_clockwise_atomic_clip.main", "draw_msaa_atlas_blit.main", "draw_msaa_image_mesh.main", "draw_msaa_path.main", @@ -210,7 +216,7 @@ def spirv_symbol_name(input_path: Path, output_type: str) -> str: def is_atomic_input(input_path: Path) -> bool: - return "atomic" in input_path.stem and "clockwise_atomic" not in input_path.stem + return "atomic" in input_path.stem def is_clockwise_input(input_path: Path) -> bool: @@ -243,6 +249,44 @@ def spirv_opt_params(input_path: Path, output_type: str) -> list[str]: return SPIRV_STANDARD_FRAG_OPT_PARAMS +def makefile_input_list(source_dir: Path, + variable: str, + fallback: list[str]) -> list[str]: + makefile = source_dir / "Makefile" + if not makefile.exists(): + return fallback + + lines = makefile.read_text(encoding="utf-8").splitlines() + prefix = f"{variable} :=" + for index, line in enumerate(lines): + stripped = line.strip() + if not stripped.startswith(prefix): + continue + + values: list[str] = [] + remainder = stripped.split(":=", 1)[1].strip() + while True: + continued = remainder.endswith("\\") + value_text = remainder[:-1].strip() if continued else remainder + values.extend(value for value in value_text.split() if value) + + if not continued: + break + index += 1 + if index >= len(lines): + break + remainder = lines[index].strip() + + normalized = [ + value.removeprefix("spirv/") + for value in values + if not value.startswith("#") + ] + return normalized or fallback + + return fallback + + def compile_spirv(source_dir: Path, out_dir: Path, glslang_validator: Path, @@ -254,6 +298,16 @@ def compile_spirv(source_dir: Path, standard_inputs = sorted(spirv_dir.glob("*.main")) standard_inputs += sorted(spirv_dir.glob("*.vert")) standard_inputs += sorted(spirv_dir.glob("*.frag")) + fixedcolor_frag_inputs = makefile_input_list( + source_dir, + "SPIRV_FIXEDCOLOR_FRAG_INPUTS", + SPIRV_FIXEDCOLOR_FRAG_INPUTS, + ) + draw_msaa_inputs = makefile_input_list( + source_dir, + "SPIRV_DRAW_MSAA_INPUTS", + SPIRV_DRAW_MSAA_INPUTS, + ) def compile_variants(input_paths: list[Path], output_types: list[str]) -> None: for output_type in output_types: @@ -303,11 +357,11 @@ def compile_variants(input_paths: list[Path], output_types: list[str]) -> None: compile_variants(standard_inputs, ["vert", "frag"]) compile_variants( - [spirv_dir / name for name in SPIRV_FIXEDCOLOR_FRAG_INPUTS], + [spirv_dir / name for name in fixedcolor_frag_inputs], ["fixedcolor_frag"], ) compile_variants( - [spirv_dir / name for name in SPIRV_DRAW_MSAA_INPUTS], + [spirv_dir / name for name in draw_msaa_inputs], ["noclipdistance_vert"], ) diff --git a/scripts/bootstrap.py b/scripts/bootstrap.py index 6d4febf..2c845ba 100644 --- a/scripts/bootstrap.py +++ b/scripts/bootstrap.py @@ -83,6 +83,15 @@ PREMAKE_GITHUB_PATTERN = re.compile( r"(?P[A-Za-z0-9_]+)\s*=\s*dependency\.github\(\s*['\"](?P[^'\"]+)['\"]\s*,\s*['\"](?P[^'\"]+)['\"]\s*\)" ) +MAKE_IMAGE_TEXTURE_DECL_PATTERN = re.compile( + r"(?P[ \t]*)(?:virtual\s+)?rcp\s+makeImageTexture\(\s*" + r"uint32_t\s+width,\s*" + r"uint32_t\s+height,\s*" + r"uint32_t\s+mipLevelCount,\s*" + r"GPUTextureFormat\s+format,\s*" + r"const\s+uint8_t\s+imageDataRGBAPremul\[\]\)\s*(?:override)?;", + re.MULTILINE, +) def run(command: list[str], cwd: Path | None = None) -> None: @@ -153,8 +162,90 @@ def gather_rive_dependencies(rive_cpp_dir: Path) -> list[dict[str, object]]: return entries +def add_make_image_texture_compat(header: Path) -> None: + if not header.exists(): + return + + text = header.read_text(encoding="utf-8") + if "GPUTextureFormat format" not in text or "GPUTextureFormat::rgba32" in text: + return + + match = MAKE_IMAGE_TEXTURE_DECL_PATTERN.search(text) + if not match: + return + + indent = match.group("indent") + continuation = indent + " " * 34 + compatibility_overload = ( + f"\n{indent}rcp makeImageTexture(uint32_t width,\n" + f"{continuation}uint32_t height,\n" + f"{continuation}uint32_t mipLevelCount,\n" + f"{continuation}const uint8_t imageDataRGBAPremul[])\n" + f"{indent}{{\n" + f"{indent} return makeImageTexture(width,\n" + f"{indent} height,\n" + f"{indent} mipLevelCount,\n" + f"{indent} GPUTextureFormat::rgba32,\n" + f"{indent} imageDataRGBAPremul);\n" + f"{indent}}}\n" + ) + + header.write_text( + text[:match.end()] + compatibility_overload + text[match.end():], + encoding="utf-8", + ) + + def apply_dependency_compatibility(target: Path, entry: dict[str, object]) -> None: if entry["path"] == "3rdparty/rive-cpp": + render_context_impl_header = ( + target + / "renderer" + / "include" + / "rive" + / "renderer" + / "render_context_impl.hpp" + ) + if render_context_impl_header.exists(): + text = render_context_impl_header.read_text(encoding="utf-8") + include = '#include "rive/renderer/texture.hpp"\n' + needle = '#include "rive/texture_archive.hpp"\n' + if include not in text and needle in text: + render_context_impl_header.write_text( + text.replace(needle, needle + include), + encoding="utf-8", + ) + + gl_render_context_header = ( + target + / "renderer" + / "include" + / "rive" + / "renderer" + / "gl" + / "render_context_gl_impl.hpp" + ) + if gl_render_context_header.exists(): + text = gl_render_context_header.read_text(encoding="utf-8") + include = '#include "rive/renderer/texture.hpp"\n' + needle = '#include "rive/renderer/render_context_helper_impl.hpp"\n' + if include not in text and needle in text: + gl_render_context_header.write_text( + text.replace(needle, needle + include), + encoding="utf-8", + ) + + renderer_include_dir = target / "renderer" / "include" / "rive" / "renderer" + for header in [ + renderer_include_dir / "d3d11" / "render_context_d3d_impl.hpp", + renderer_include_dir / "d3d12" / "render_context_d3d12_impl.hpp", + renderer_include_dir / "gl" / "render_context_gl_impl.hpp", + renderer_include_dir / "metal" / "render_context_metal_impl.h", + renderer_include_dir / "vulkan" / "render_context_vulkan_impl.hpp", + renderer_include_dir / "webgpu" / "render_context_webgpu_impl.hpp", + ]: + add_make_image_texture_compat(header) + gl_render_context = target / "renderer" / "src" / "gl" / "render_context_gl_impl.cpp" if gl_render_context.exists(): text = gl_render_context.read_text(encoding="utf-8")