diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 2b9ba431e2..56b7962aa0 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -5,5 +5,5 @@ repositories { } } dependencies { - implementation "edu.wpi.first:native-utils:2023.2.7" + implementation "edu.wpi.first:native-utils:2023.3.0" } diff --git a/cscore/build.gradle b/cscore/build.gradle index c1a7243164..6f3a678d63 100644 --- a/cscore/build.gradle +++ b/cscore/build.gradle @@ -180,7 +180,7 @@ model { components { examplesMap.each { key, value -> if (key == "usbviewer") { - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { + if (!project.hasProperty('onlylinuxathena')) { "${key}"(NativeExecutableSpec) { targetBuildTypes 'debug' binaries.all { @@ -189,7 +189,7 @@ model { lib project: ':wpigui', library: 'wpigui', linkage: 'static' lib library: 'cscore', linkage: 'shared' nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -199,6 +199,9 @@ model { it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } sources { diff --git a/datalogtool/build.gradle b/datalogtool/build.gradle index c7f1c158b5..9d89ce5ddf 100644 --- a/datalogtool/build.gradle +++ b/datalogtool/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { description = "roboRIO Team Number Setter" @@ -24,19 +24,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar def wpilibVersionFileInput = file("src/main/generate/WPILibVersion.cpp.in") def wpilibVersionFileOutput = file("$buildDir/generated/main/cpp/WPILibVersion.cpp") - nativeUtils { - nativeDependencyContainer { - libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { - groupId = "edu.wpi.first.thirdparty.frc2023" - artifactId = "libssh" - headerClassifier = "headers" - sourceClassifier = "sources" - ext = "zip" - version = '0.95-3' - targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms) - } - } - } + apply from: "${rootDir}/shared/libssh.gradle" task generateCppVersion() { description = 'Generates the wpilib version class' @@ -107,7 +95,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -124,6 +112,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Kerberos' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } } diff --git a/fieldImages/build.gradle b/fieldImages/build.gradle index 369d72a3b3..123e89d4db 100644 --- a/fieldImages/build.gradle +++ b/fieldImages/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { apply plugin: 'cpp' apply plugin: 'c' diff --git a/glass/build.gradle b/glass/build.gradle index b9e62572c4..1d890118e9 100644 --- a/glass/build.gradle +++ b/glass/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { description = "A different kind of dashboard" @@ -100,7 +100,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -128,7 +128,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -169,7 +169,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -190,6 +190,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } } diff --git a/outlineviewer/build.gradle b/outlineviewer/build.gradle index f7d18bcfe4..466bed5db5 100644 --- a/outlineviewer/build.gradle +++ b/outlineviewer/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { description = "NetworkTables Viewer" @@ -93,7 +93,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -110,6 +110,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } } diff --git a/roborioteamnumbersetter/build.gradle b/roborioteamnumbersetter/build.gradle index 2ca1215b2e..5099e9edd0 100644 --- a/roborioteamnumbersetter/build.gradle +++ b/roborioteamnumbersetter/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { description = "roboRIO Team Number Setter" @@ -24,19 +24,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar def wpilibVersionFileInput = file("src/main/generate/WPILibVersion.cpp.in") def wpilibVersionFileOutput = file("$buildDir/generated/main/cpp/WPILibVersion.cpp") - nativeUtils { - nativeDependencyContainer { - libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { - groupId = "edu.wpi.first.thirdparty.frc2023" - artifactId = "libssh" - headerClassifier = "headers" - sourceClassifier = "sources" - ext = "zip" - version = '0.95-3' - targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms) - } - } - } + apply from: "${rootDir}/shared/libssh.gradle" task generateCppVersion() { description = 'Generates the wpilib version class' @@ -107,7 +95,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -125,6 +113,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Kerberos' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } } diff --git a/shared/config.gradle b/shared/config.gradle index d97d004aa9..6838a7fada 100644 --- a/shared/config.gradle +++ b/shared/config.gradle @@ -17,7 +17,7 @@ nativeUtils { niLibVersion = "2023.1.0" opencvVersion = "4.6.0-2" googleTestVersion = "1.11.0-3" - imguiVersion = "1.88-5" + imguiVersion = "1.88-8" wpimathVersion = "-1" } } diff --git a/shared/libssh.gradle b/shared/libssh.gradle new file mode 100644 index 0000000000..08fab4ff39 --- /dev/null +++ b/shared/libssh.gradle @@ -0,0 +1,13 @@ +nativeUtils { + nativeDependencyContainer { + libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) { + groupId = "edu.wpi.first.thirdparty.frc2023" + artifactId = "libssh" + headerClassifier = "headers" + sourceClassifier = "sources" + ext = "zip" + version = '0.95-5' + targetPlatforms.addAll(nativeUtils.wpi.platforms.allPlatforms) + } + } +} diff --git a/shared/plugins/setupBuild.gradle b/shared/plugins/setupBuild.gradle index 3caa30a3f7..91cbf11ddf 100644 --- a/shared/plugins/setupBuild.gradle +++ b/shared/plugins/setupBuild.gradle @@ -57,7 +57,7 @@ if (!project.hasProperty('onlylinuxathena')) { } } binaries.all { - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { + if (!project.hasProperty('onlylinuxathena')) { project(':hal').addHalDependency(it, 'shared') lib library: pluginName if (project.hasProperty('includeNtCore')) { @@ -84,7 +84,7 @@ if (!project.hasProperty('onlylinuxathena')) { model { tasks { def c = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { + if (!project.hasProperty('onlylinuxathena')) { project.tasks.create('runCpp', Exec) { group = 'WPILib' description = "Run the ${pluginName}Dev executable" diff --git a/simulation/halsim_ds_socket/build.gradle b/simulation/halsim_ds_socket/build.gradle index 186903e8eb..0e90938df6 100644 --- a/simulation/halsim_ds_socket/build.gradle +++ b/simulation/halsim_ds_socket/build.gradle @@ -21,7 +21,7 @@ apply from: "${rootDir}/shared/plugins/setupBuild.gradle" model { testSuites { def comps = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { + if (!project.hasProperty('onlylinuxathena')) { "${pluginName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : comps) { if (c.name == pluginName) { diff --git a/simulation/halsim_gui/build.gradle b/simulation/halsim_gui/build.gradle index fa4ccd957e..e11d7fb121 100644 --- a/simulation/halsim_gui/build.gradle +++ b/simulation/halsim_gui/build.gradle @@ -1,4 +1,4 @@ -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { description = "A plugin that creates a simulation gui" @@ -29,7 +29,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar lib project: ':wpinet', library: 'wpinet', linkage: 'shared' lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared' nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -39,6 +39,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } } diff --git a/simulation/halsim_ws_server/build.gradle b/simulation/halsim_ws_server/build.gradle index e4eb6c2f70..fbdee04de4 100644 --- a/simulation/halsim_ws_server/build.gradle +++ b/simulation/halsim_ws_server/build.gradle @@ -21,7 +21,7 @@ apply from: "${rootDir}/shared/plugins/setupBuild.gradle" model { testSuites { def comps = $.components - if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { + if (!project.hasProperty('onlylinuxathena')) { "${pluginName}Test"(GoogleTestTestSuiteSpec) { for(NativeComponentSpec c : comps) { if (c.name == pluginName) { diff --git a/wpigui/build.gradle b/wpigui/build.gradle index 40b0a52243..7b28843938 100644 --- a/wpigui/build.gradle +++ b/wpigui/build.gradle @@ -1,6 +1,6 @@ import org.gradle.internal.os.OperatingSystem -if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) { +if (!project.hasProperty('onlylinuxathena')) { apply plugin: 'cpp' if (OperatingSystem.current().isMacOsX()) { @@ -49,7 +49,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } binaries.all { nativeUtils.useRequiredLibrary(it, 'imgui_static') - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -71,9 +71,18 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } } } + } else if (it.targetPlatform.name.startsWith('linuxarm')) { + it.sources { + wpiguiUnixGl2Cpp(CppSourceSet) { + source { + srcDirs 'src/main/native/opengl2' + include '*.cpp' + } + } + } } else { it.sources { - wpiguiUnixCpp(CppSourceSet) { + wpiguiUnixGl3Cpp(CppSourceSet) { source { srcDirs 'src/main/native/opengl3' include '*.cpp' @@ -111,7 +120,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar } binaries { all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) { + if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio) { it.buildable = false return } @@ -121,6 +130,9 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxar it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { it.linker.args << '-lX11' + if (it.targetPlatform.name.startsWith('linuxarm')) { + it.linker.args << '-lGL' + } } } withType(SharedLibraryBinarySpec) { diff --git a/wpigui/src/main/native/opengl2/wpigui_opengl2.cpp b/wpigui/src/main/native/opengl2/wpigui_opengl2.cpp new file mode 100644 index 0000000000..f0324eb5d4 --- /dev/null +++ b/wpigui/src/main/native/opengl2/wpigui_opengl2.cpp @@ -0,0 +1,131 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include + +#include +#include +#include +#include + +#include "wpigui.h" +#include "wpigui_internal.h" + +using namespace wpi::gui; + +static bool gPlatformValid = false; + +namespace wpi { + +void gui::PlatformCreateContext() {} + +void gui::PlatformDestroyContext() {} + +void gui::PlatformGlfwInitHints() {} + +void gui::PlatformGlfwWindowHints() { + // GL 2.1 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + + // enable 4xMSAA + glfwWindowHint(GLFW_SAMPLES, 4); +} + +bool gui::PlatformInitRenderer() { + glfwMakeContextCurrent(gContext->window); + + glfwSwapInterval(1); // Enable vsync + + // Turn on multisampling + glEnable(GL_MULTISAMPLE); + + // Setup Platform/Renderer bindings + ImGui_ImplGlfw_InitForOpenGL(gContext->window, true); + + ImGui_ImplOpenGL2_Init(); + + gPlatformValid = true; + return true; +} + +void gui::PlatformRenderFrame() { + ImGui_ImplOpenGL2_NewFrame(); + + CommonRenderFrame(); + + int display_w, display_h; + glfwGetFramebufferSize(gContext->window, &display_w, &display_h); + glViewport(0, 0, display_w, display_h); + glClearColor(gContext->clearColor.x, gContext->clearColor.y, + gContext->clearColor.z, gContext->clearColor.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); + + glfwSwapBuffers(gContext->window); +} + +void gui::PlatformShutdown() { + gPlatformValid = false; + ImGui_ImplOpenGL2_Shutdown(); +} + +void gui::PlatformFramebufferSizeChanged(int width, int height) {} + +static inline GLenum GLPixelFormat(PixelFormat format) { + switch (format) { + case kPixelRGBA: + return GL_RGBA; + case kPixelBGRA: + return GL_BGRA; + default: + return GL_RGBA; + } +} + +ImTextureID gui::CreateTexture(PixelFormat format, int width, int height, + const unsigned char* data) { + if (!gPlatformValid) { + return nullptr; + } + + // Create a OpenGL texture identifier + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + // Setup filtering parameters for display + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Upload pixels into texture + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GLPixelFormat(format), GL_UNSIGNED_BYTE, data); + + return reinterpret_cast(static_cast(texture)); +} + +void gui::UpdateTexture(ImTextureID texture, PixelFormat format, int width, + int height, const unsigned char* data) { + GLuint glTexture = static_cast(reinterpret_cast(texture)); + if (glTexture == 0) { + return; + } + glBindTexture(GL_TEXTURE_2D, glTexture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GLPixelFormat(format), + GL_UNSIGNED_BYTE, data); +} + +void gui::DeleteTexture(ImTextureID texture) { + if (!gPlatformValid) { + return; + } + GLuint glTexture = static_cast(reinterpret_cast(texture)); + if (glTexture != 0) { + glDeleteTextures(1, &glTexture); + } +} + +} // namespace wpi