Skip to content

Commit 25bca44

Browse files
tychedeliacatilacStefterv
authored
Merge WebGPU backend (#1514)
* *:ꔫ:*Renderer Project*:ꔫ:* * Create workspaces for ffi and the renderer (#1275) * Inital scaffold for libprocessing ffi. * Remove EAP. * Update docs. * Factor out gradle utils. Add flag for disabling webgpu and enforcing android source level compat. * Remove processing.h * Set java version for all projects. * libprocessing ffi error handling (#1293) * FFI error setup * Clear before init. * Basic app lifecycle / surface creation. * Throw when not on macos. * Implement `background` method (#1308) * Implement background. * Install wayland deps. * Support for windows surfaces. (#1310) * Implement basic rendering flow (#1322) * Implement basic rendering flow * Fix naming. * Actually fix rename. * libprocessing submodule * --recursive when cloning repo * Enable submodule checkout in Gradle workflow Added support for submodules in the checkout step. * Enable submodules in checkout steps Added submodule support to the checkout steps. * Wayland support with new WebGPU renderer * Gradle fixes from libprocessing refactor. (#1346) * Updates from libprocessing. (#1392) * Updates from libprocessing. * Fixes for compat with main 17. * Fixup docs. * Upgrade to jdk-25. * Upgrade to jdk-25. * Materials, lights, input event forwarding, ellipse fix. * Get the gradle sketch runner working locally. * Conditionally execute webgpu tests * ProcessingLibraryPlugin JVM Toggle update * 4.5.5 in gradle.properties * ProcessingPlugin fixes --------- Co-authored-by: Moon D. <moon@softmoon.world> Co-authored-by: Moon <catilac@users.noreply.github.com> Co-authored-by: Stef Tervelde <stef@steftervelde.nl>
1 parent ab9a225 commit 25bca44

51 files changed

Lines changed: 3753 additions & 246 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ generated/
139139
/java/gradle/build
140140
/core/examples/build
141141
/java/gradle/example/.processing
142+
143+
libprocessing/ffi/include/*
142144
/app/windows/obj
143145
/java/android/example/build
144146
/java/android/example/.processing

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "libprocessing"]
2+
path = libprocessing
3+
url = https://github.com/processing/libprocessing

BUILD.md

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ _**Note:** A paid subscription is **not** required. Everything needed to build a
2323
> [!TIP]
2424
> If you encounter any issues with this process, Read the [Troubleshooting and Setup Tips for IntelliJ IDEA](#troubleshooting-and-setup-tips-intellij-idea)
2525
26+
1. Clone the Processing4 repository to your machine locally
27+
1. Open the cloned repository in IntelliJ IDEA CE
28+
1. When prompted, select **Trust Project**. You can preview the project in Safe Mode but you won't be able to build Processing.
29+
1. IntelliJ may ask if you want to load Gradle project. If you allow this, make sure you are using JDK version 17.
30+
1. In the main menu, go to File > Project Structure > Project Settings > Project.
31+
1. In the SDK Dropdown option, select a JDK version 17 or Download the jdk
32+
1. Click the green Run Icon in the top right of the window. This is also where you can find the option to debug Processing.
33+
1. Logs can be found in the `Build` or `Debug` pane on the bottom left of the window
34+
35+
2636
## VSCode
2737
1. Clone the Processing4 repository to your machine locally
2838
1. Open the cloned repository in VScode
@@ -46,7 +56,7 @@ If you don't have them installed, you will need to install [Git](https://git-scm
4656

4757
1. **Clone the repository:**
4858
```bash
49-
git clone https://github.com/processing/processing4.git
59+
git clone --recursive https://github.com/processing/processing4.git
5060
cd processing4
5161
```
5262

@@ -58,8 +68,49 @@ If you don't have them installed, you will need to install [Git](https://git-scm
5868
- [macOS (Apple Silicon)](https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.15%2B6/OpenJDK17U-jdk_aarch64_mac_hotspot_17.0.15_6.pkg)
5969
- [Other platforms](https://adoptium.net/temurin/releases/?package=jdk&version=17&os=any&arch=any)
6070

71+
### macOS:
72+
```bash
73+
brew install --cask temurin@17
74+
````
75+
76+
### Windows (using winget):
77+
```bash
78+
winget install --id=EclipseAdoptium.Temurin.17.JDK -e
79+
```
80+
81+
### SDKMAN!
82+
83+
[SDKMAN!](https://sdkman.io/) is a useful tool for developers working on multiple versions of the JVM.
84+
85+
## WebGPU Support (Optional)
86+
87+
To build Processing with the experimental WebGPU renderer, you need JDK 25, Rust, and jextract.
88+
89+
### Install Temurin JDK 25
90+
91+
```bash
92+
brew install --cask temurin@25 # macOS
93+
```
94+
95+
### Install `jextract`
96+
97+
`jextract` generates Java bindings from C header files.
98+
You can download it [here](https://jdk.java.net/jextract/) or install it using SDKMAN!:
99+
100+
```bash
101+
sdk install jextract
102+
````
103+
104+
### Build with WebGPU
105+
106+
```bash
107+
./gradlew build -PenableWebGPU=true
108+
```
109+
61110
3. **Set the `JAVA_HOME` environment variable:**
62111

112+
It may be necessary to set the `JAVA_HOME` environment variable to point to your Temurin JDK installation.
113+
63114
```bash
64115
export JAVA_HOME=/path/to/temurin/jdk-17.0.15+6/
65116
```
@@ -142,32 +193,24 @@ If you’re building Processing using IntelliJ IDEA and something’s not workin
142193
143194
### Use the Correct JDK (temurin-17)
144195
145-
Make sure IntelliJ is using **temurin-17**. Some users have reported issues with other distributions.
146-
147-
#### 1. Set the Project SDK
196+
Make sure IntelliJ is using **temurin-17**, not another version. If building with WebGPU (`-PenableWebGPU=true`), use **temurin-25** instead.
148197
149-
1. Go to **`File > Project Structure > Project`**
150-
1. Set the **`Project SDK`** to **`temurin-17`**
198+
1. Go to **File > Project Structure > Project**
199+
2. Set the **Project SDK** to: `temurin-17 java version "17.0.15"`
151200
152201
![JDK Selection](.github/media/troubleshooting-Intellij-setting-djk-version-manually.png)
153202
154-
If Temurin 17 is not on the list, you should install it first:
155-
156-
1. Select the **`Download JDK...`** option from the menu
157-
1. Pick **Version**: **`17`**, **Vendor**: **`Eclipse Temurin (AdoptOpenJDK HotSpot)`**
203+
If it is not already installed, you can download it by:
204+
1. Clicking the SDK input field and then selecting the `Download JDK...` option from the menu
205+
2. Select Version: `17`, Vendor: `Eclipse Temurin (AdoptOpenJDK HotSpot)`
158206
159207
<img width="400" alt="JDK Download" src="https://github.com/user-attachments/assets/503a03a4-3e53-4406-9641-2c93e4b45d51" />
160208
161-
#### 2. Set the Gradle JVM
162-
163-
Make sure Gradle also uses Temurin 17:
164-
165-
1. Go to **`Settings > Build, Execution, Deployment > Build Tools > Gradle`**
166-
1. Set **`Gradle JVM`** to **`temurin-17`**
209+
![JDK Download](.github/media/troubleshooting-Intellij-download-jdk.png)
167210
168-
_Note: the exact path in settings may vary depending on your version of IntelliJ._
211+
Now go back to your main window and
212+
1. Click the green Run Icon in the top right of the window.
169213
170-
<img width="800" alt="Gradle JVM" src="https://github.com/user-attachments/assets/ba620114-e663-4887-89e9-8f26fbfefbb2" />
171214
172215
### “Duplicate content roots detected”
173216

app/build.gradle.kts

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,17 @@ compose.desktop {
5454
application {
5555
mainClass = "processing.app.ProcessingKt"
5656

57-
jvmArgs(*listOf(
58-
Pair("processing.version", rootProject.version),
59-
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
60-
Pair("processing.contributions.source", "https://contributions.processing.org/contribs"),
61-
Pair("processing.download.page", "https://processing.org/download/"),
62-
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
63-
Pair("processing.tutorials", "https://processing.org/tutorials/"),
64-
).map { "-D${it.first}=${it.second}" }.toTypedArray())
57+
jvmArgs(
58+
"--enable-native-access=ALL-UNNAMED", // Required for Java 25 native library access
59+
*listOf(
60+
Pair("processing.version", rootProject.version),
61+
Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE),
62+
Pair("processing.contributions.source", "https://contributions.processing.org/contribs"),
63+
Pair("processing.download.page", "https://processing.org/download/"),
64+
Pair("processing.download.latest", "https://processing.org/download/latest.txt"),
65+
Pair("processing.tutorials", "https://processing.org/tutorials/"),
66+
).map { "-D${it.first}=${it.second}" }.toTypedArray()
67+
)
6568

6669
nativeDistributions{
6770
modules("jdk.jdi", "java.compiler", "jdk.accessibility", "jdk.zipfs", "java.management.rmi", "java.scripting", "jdk.httpserver")
@@ -139,11 +142,12 @@ dependencies {
139142
testImplementation(libs.mockitoKotlin)
140143
testImplementation(libs.junitJupiter)
141144
testImplementation(libs.junitJupiterParams)
145+
146+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
142147

143148
}
144149

145150
tasks.test {
146-
systemProperty("java.awt.headless", "true")
147151
useJUnitPlatform()
148152
workingDir = file("build/test")
149153
workingDir.mkdirs()
@@ -363,12 +367,12 @@ tasks.register<Zip>("zipDistributable"){
363367
dependsOn("createDistributable", "setExecutablePermissions")
364368
group = "compose desktop"
365369

366-
val dir = provider { distributable().destinationDir.get() }
367-
val packageName = provider { distributable().packageName.get() }
370+
val dir = distributable().destinationDir.get()
371+
val packageName = distributable().packageName.get()
368372

369373
from(dir){ eachFile{ permissions{ unix("755") } } }
370374
archiveBaseName.set(packageName)
371-
destinationDirectory.set(layout.dir(provider { dir.get().file("../").asFile }))
375+
destinationDirectory.set(dir.file("../").asFile)
372376
}
373377

374378
afterEvaluate{
@@ -434,12 +438,19 @@ tasks.register<Copy>("includeJavaMode") {
434438
from(java.configurations.runtimeClasspath)
435439
into(composeResources("modes/java/mode"))
436440
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
441+
dirPermissions { unix("rwx------") }
437442
}
443+
val enableWebGPU = findProperty("enableWebGPU")?.toString()?.toBoolean() ?: false
444+
438445
tasks.register<Copy>("includeJdk") {
439-
from(Jvm.current().javaHome.absolutePath)
446+
val jdkVersion = if (enableWebGPU) 25 else 17
447+
val jdkHome = project.the<JavaToolchainService>().launcherFor {
448+
languageVersion.set(JavaLanguageVersion.of(jdkVersion))
449+
}.map { it.metadata.installationPath.asFile }
450+
451+
from(jdkHome)
440452
destinationDir = composeResources("jdk").get().asFile
441453

442-
dirPermissions { unix("rwx------") }
443454
fileTree(destinationDir).files.forEach { file ->
444455
file.setWritable(true, false)
445456
file.setReadable(true, false)
@@ -520,15 +531,14 @@ tasks.register("includeProcessingResources"){
520531
finalizedBy("signResources")
521532
}
522533

523-
tasks.register("signResources"){
534+
tasks.register("signResources") {
524535
onlyIf {
525536
OperatingSystem.current().isMacOsX
526537
&&
527538
compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
528539
}
529540
group = "compose desktop"
530541
val resourcesPath = composeResources("")
531-
val entitlements = file("macos/entitlements.plist").absolutePath
532542

533543
// find jars in the resources directory
534544
val jars = mutableListOf<File>()
@@ -566,8 +576,11 @@ tasks.register("signResources"){
566576
exclude("*.jar")
567577
exclude("*.so")
568578
exclude("*.dll")
569-
}.forEach{ file ->
570-
Runtime.getRuntime().exec(arrayOf("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--entitlements", entitlements, "--sign", "Developer ID Application", file.absolutePath))
579+
}.forEach{ f ->
580+
ProcessBuilder("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--sign", "Developer ID Application", f.absolutePath)
581+
.inheritIO()
582+
.start()
583+
.waitFor()
571584
}
572585
jars.forEach { file ->
573586
FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos ->
@@ -618,7 +631,6 @@ tasks.register<Exec>("signApp"){
618631
"--force",
619632
"--deep",
620633
"--options=runtime",
621-
"--entitlements", file("macos/entitlements.plist").absolutePath,
622634
"--sign", "Developer ID Application",
623635
app)
624636
}

app/utils/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ repositories {
1010
dependencies {
1111
testImplementation(platform("org.junit:junit-bom:5.10.0"))
1212
testImplementation("org.junit.jupiter:junit-jupiter")
13+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
1314
}
1415

1516
publishing{
@@ -23,4 +24,4 @@ publishing{
2324

2425
tasks.test {
2526
useJUnitPlatform()
26-
}
27+
}

build.gradle.kts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,35 @@ plugins {
1212
// Can be deleted after the migration to Gradle is complete
1313
layout.buildDirectory = file(".build")
1414

15+
val enableWebGPU = findProperty("enableWebGPU")?.toString()?.toBoolean() ?: false
16+
val javaVersion = if (enableWebGPU) "25" else "17"
17+
val kotlinJvmTarget = if (enableWebGPU) {
18+
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_25
19+
} else {
20+
org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
21+
}
22+
23+
allprojects {
24+
tasks.withType<JavaCompile>().configureEach {
25+
sourceCompatibility = javaVersion
26+
targetCompatibility = javaVersion
27+
}
28+
29+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
30+
compilerOptions {
31+
jvmTarget.set(kotlinJvmTarget)
32+
}
33+
}
34+
35+
plugins.withType<JavaPlugin> {
36+
extensions.configure<JavaPluginExtension> {
37+
toolchain {
38+
languageVersion.set(JavaLanguageVersion.of(javaVersion.toInt()))
39+
}
40+
}
41+
}
42+
}
43+
1544
// Configure the dependencyUpdates task
1645
tasks {
1746
dependencyUpdates {

buildSrc/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
plugins {
2+
`kotlin-dsl`
3+
}
4+
5+
repositories {
6+
mavenCentral()
7+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package processing.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.file.RegularFileProperty
6+
import org.gradle.api.provider.Property
7+
import org.gradle.api.tasks.*
8+
import org.gradle.process.ExecOperations
9+
import javax.inject.Inject
10+
11+
abstract class CargoBuildTask : DefaultTask() {
12+
13+
@get:Inject
14+
abstract val execOperations: ExecOperations
15+
16+
@get:InputDirectory
17+
abstract val cargoWorkspaceDir: DirectoryProperty
18+
19+
@get:Input
20+
abstract val manifestPath: Property<String>
21+
22+
@get:Input
23+
abstract val release: Property<Boolean>
24+
25+
@get:Input
26+
abstract val cargoPath: Property<String>
27+
28+
@get:OutputFile
29+
abstract val outputLibrary: RegularFileProperty
30+
31+
init {
32+
group = "rust"
33+
description = "Builds Rust library using cargo"
34+
35+
// release by default
36+
release.convention(true)
37+
}
38+
39+
@TaskAction
40+
fun build() {
41+
val buildType = if (release.get()) "release" else "debug"
42+
logger.lifecycle("Building Rust library ($buildType mode)...")
43+
44+
val args = mutableListOf("build")
45+
if (release.get()) {
46+
args.add("--release")
47+
}
48+
args.add("--manifest-path")
49+
args.add(manifestPath.get())
50+
51+
execOperations.exec {
52+
workingDir = cargoWorkspaceDir.get().asFile
53+
commandLine = listOf(cargoPath.get()) + args
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)