From c02577bb517949cc97d3a85a1633b9f1216daa51 Mon Sep 17 00:00:00 2001 From: Thad House Date: Sun, 19 Dec 2021 14:19:24 -0800 Subject: [PATCH] [glass] Configure delay loading for windows camera server support (#3803) We don't currently support cameras in glass, but it's something we want to do in the future. However, when we do this, glass will completely stop working on N builds of windows, and it would fail to load at all with no messages. To solve this, we can delayload the media foundation dlls that are missing. The executable will then launch even without the dlls present, and we can attempt to load them at runtime and dynamically disable camera support. When we get around to implementing it, we can just call HasCameraSupport, and dynamically hide all camera related code behind that flag. --- glass/build.gradle | 3 ++ glass/src/app/native/cpp/camerasupport.cpp | 52 ++++++++++++++++++++++ glass/src/app/native/cpp/camerasupport.h | 9 ++++ 3 files changed, 64 insertions(+) create mode 100644 glass/src/app/native/cpp/camerasupport.cpp create mode 100644 glass/src/app/native/cpp/camerasupport.h diff --git a/glass/build.gradle b/glass/build.gradle index ad977ada0a..cd77f45a0b 100644 --- a/glass/build.gradle +++ b/glass/build.gradle @@ -185,15 +185,18 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra it.buildable = false return } + lib project: ':cscore', library: 'cscore', linkage: 'static' lib library: 'glassnt', linkage: 'static' lib library: nativeName, linkage: 'static' lib project: ':ntcore', library: 'ntcore', linkage: 'static' lib project: ':wpiutil', library: 'wpiutil', linkage: 'static' lib project: ':wpimath', library: 'wpimath', linkage: 'static' lib project: ':wpigui', library: 'wpigui', linkage: 'static' + nativeUtils.useRequiredLibrary(it, 'opencv_static') nativeUtils.useRequiredLibrary(it, 'imgui_static') if (it.targetPlatform.operatingSystem.isWindows()) { it.linker.args << 'Gdi32.lib' << 'Shell32.lib' << 'd3d11.lib' << 'd3dcompiler.lib' + it.linker.args << '/DELAYLOAD:MF.dll' << '/DELAYLOAD:MFReadWrite.dll' << '/DELAYLOAD:MFPlat.dll' << '/delay:nobind' } else if (it.targetPlatform.operatingSystem.isMacOsX()) { it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' } else { diff --git a/glass/src/app/native/cpp/camerasupport.cpp b/glass/src/app/native/cpp/camerasupport.cpp new file mode 100644 index 0000000000..eda3e6e829 --- /dev/null +++ b/glass/src/app/native/cpp/camerasupport.cpp @@ -0,0 +1,52 @@ +// 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 "camerasupport.h" + +#ifdef _WIN32 +#include "Windows.h" +#include "delayimp.h" +#pragma comment(lib, "delayimp.lib") +static int CheckDelayException(int exception_value) { + if (exception_value == + VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) || + exception_value == + VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)) { + // This example just executes the handler. + return EXCEPTION_EXECUTE_HANDLER; + } + // Don't attempt to handle other errors + return EXCEPTION_CONTINUE_SEARCH; +} +static bool TryDelayLoadAllImports(LPCSTR szDll) { + __try { + HRESULT hr = __HrLoadAllImportsForDll(szDll); + if (FAILED(hr)) { + return false; + } + } __except (CheckDelayException(GetExceptionCode())) { + return false; + } + return true; +} +namespace glass { +bool HasCameraSupport() { + bool hasCameraSupport = false; + hasCameraSupport = TryDelayLoadAllImports("MF.dll"); + if (hasCameraSupport) { + hasCameraSupport = TryDelayLoadAllImports("MFPlat.dll"); + } + if (hasCameraSupport) { + hasCameraSupport = TryDelayLoadAllImports("MFReadWrite.dll"); + } + return hasCameraSupport; +} +} // namespace glass +#else +namespace glass { +bool HasCameraSupport() { + return true; +} +} // namespace glass +#endif diff --git a/glass/src/app/native/cpp/camerasupport.h b/glass/src/app/native/cpp/camerasupport.h new file mode 100644 index 0000000000..0be62c73ba --- /dev/null +++ b/glass/src/app/native/cpp/camerasupport.h @@ -0,0 +1,9 @@ +// 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. + +#pragma once + +namespace glass { +bool HasCameraSupport(); +} // namespace glass