diff --git a/.github/workflows/flutter-build.yml b/.github/workflows/flutter-build.yml
index 376df29fb..bb3e0706f 100644
--- a/.github/workflows/flutter-build.yml
+++ b/.github/workflows/flutter-build.yml
@@ -114,7 +114,7 @@ jobs:
         run: |
           Invoke-WebRequest -Uri https://github.com/rustdesk-org/rdev/releases/download/usbmmidd_v2/usbmmidd_v2.zip -OutFile usbmmidd_v2.zip
           Expand-Archive usbmmidd_v2.zip -DestinationPath .
-          python3 .\build.py --portable --hwcodec --flutter --vram --skip-portable-pack --virtual-display
+          python3 .\build.py --portable --hwcodec --flutter --vram --skip-portable-pack
           Remove-Item -Path usbmmidd_v2\Win32 -Recurse
           Remove-Item -Path "usbmmidd_v2\deviceinstaller64.exe", "usbmmidd_v2\deviceinstaller.exe", "usbmmidd_v2\usbmmidd.bat"
           mv ./flutter/build/windows/x64/runner/Release ./rustdesk
@@ -256,7 +256,7 @@ jobs:
           python3 res/inline-sciter.py
           # Patch sciter x86
           sed -i 's/branch = "dyn"/branch = "dyn_x86"/g' ./Cargo.toml
-          cargo build --features inline,vram,hwcodec,virtual_display_driver --release --bins
+          cargo build --features inline,vram,hwcodec --release --bins
           mkdir -p ./Release
           mv ./target/release/rustdesk.exe ./Release/rustdesk.exe
           curl -LJ -o ./Release/sciter.dll https://github.com/c-smile/sciter-sdk/raw/master/bin.win/x32/sciter.dll
diff --git a/Cargo.toml b/Cargo.toml
index 05a11d0aa..5c35652b9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,7 +28,6 @@ default = ["use_dasp"]
 hwcodec = ["scrap/hwcodec"]
 vram = ["scrap/vram"]
 mediacodec = ["scrap/mediacodec"]
-virtual_display_driver = ["virtual_display"]
 plugin_framework = []
 linux-pkg-config = ["magnum-opus/linux-pkg-config", "scrap/linux-pkg-config"]
 unix-file-copy-paste = [
@@ -112,7 +111,7 @@ winapi = { version = "0.3", features = [
 ] }
 winreg = "0.11"
 windows-service = "0.6"
-virtual_display = { path = "libs/virtual_display", optional = true }
+virtual_display = { path = "libs/virtual_display" }
 impersonate_system = { git = "https://github.com/21pages/impersonate-system" }
 shared_memory = "0.12"
 tauri-winrt-notification = "0.1.2"
diff --git a/build.py b/build.py
index cdcf2994d..c3885c3b7 100755
--- a/build.py
+++ b/build.py
@@ -145,12 +145,6 @@ def make_parser():
             action='store_true',
             help='Skip packing, only flutter version + Windows supported'
         )
-        parser.add_argument(
-            '--virtual-display',
-            action='store_true',
-            default=False,
-            help='Build rustdesk libs with the virtual display feature enabled'
-        )
     parser.add_argument(
         "--package",
         type=str
@@ -288,9 +282,6 @@ def get_features(args):
             features.append('flutter_texture_render')
     if args.unix_file_copy_paste:
         features.append('unix-file-copy-paste')
-    if windows:
-        if args.virtual_display:
-            features.append('virtual_display_driver')
     print("features:", features)
     return features
 
diff --git a/src/core_main.rs b/src/core_main.rs
index 5055626cd..5e5c36ef4 100644
--- a/src/core_main.rs
+++ b/src/core_main.rs
@@ -218,7 +218,7 @@ pub fn core_main() -> Option<Vec<String>> {
                 hbb_common::allow_err!(crate::platform::windows::uninstall_cert());
                 return None;
             } else if args[0] == "--install-idd" {
-                #[cfg(all(windows, feature = "virtual_display_driver"))]
+                #[cfg(windows)]
                 if crate::virtual_display_manager::is_virtual_display_supported() {
                     hbb_common::allow_err!(
                         crate::virtual_display_manager::rustdesk_idd::install_update_driver()
@@ -233,7 +233,7 @@ pub fn core_main() -> Option<Vec<String>> {
                 );
                 return None;
             } else if args[0] == "--uninstall-amyuni-idd" {
-                #[cfg(all(windows, feature = "virtual_display_driver"))]
+                #[cfg(windows)]
                 hbb_common::allow_err!(
                     crate::virtual_display_manager::amyuni_idd::uninstall_driver()
                 );
@@ -266,7 +266,7 @@ pub fn core_main() -> Option<Vec<String>> {
             return None;
         } else if args[0] == "--server" {
             log::info!("start --server with user {}", crate::username());
-            #[cfg(all(windows, feature = "virtual_display_driver"))]
+            #[cfg(windows)]
             crate::privacy_mode::restore_reg_connectivity(true);
             #[cfg(any(target_os = "linux", target_os = "windows"))]
             {
diff --git a/src/lib.rs b/src/lib.rs
index 2bdef3bbd..1794dff9d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -66,5 +66,5 @@ pub mod clipboard_file;
 
 pub mod privacy_mode;
 
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub mod virtual_display_manager;
diff --git a/src/privacy_mode.rs b/src/privacy_mode.rs
index c062fbff8..7116095f1 100644
--- a/src/privacy_mode.rs
+++ b/src/privacy_mode.rs
@@ -1,4 +1,4 @@
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 use crate::platform::is_installed;
 use crate::ui_interface::get_option;
 #[cfg(windows)]
@@ -27,9 +27,9 @@ pub mod win_mag;
 #[cfg(windows)]
 pub mod win_topmost_window;
 
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 mod win_virtual_display;
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub use win_virtual_display::restore_reg_connectivity;
 
 pub const INVALID_PRIVACY_MODE_CONN_ID: i32 = 0;
@@ -44,7 +44,7 @@ pub const PRIVACY_MODE_IMPL_WIN_MAG: &str = win_mag::PRIVACY_MODE_IMPL;
 pub const PRIVACY_MODE_IMPL_WIN_EXCLUDE_FROM_CAPTURE: &str =
     win_exclude_from_capture::PRIVACY_MODE_IMPL;
 
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub const PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY: &str = win_virtual_display::PRIVACY_MODE_IMPL;
 
 #[derive(Debug, Serialize, Deserialize, Clone)]
@@ -103,16 +103,9 @@ lazy_static::lazy_static! {
                 if display_service::is_privacy_mode_mag_supported() {
                     PRIVACY_MODE_IMPL_WIN_MAG
                 } else {
-                    #[cfg(feature = "virtual_display_driver")]
-                    {
-                        if is_installed() {
-                            PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY
-                        } else {
-                            ""
-                        }
-                    }
-                    #[cfg(not(feature = "virtual_display_driver"))]
-                    {
+                    if is_installed() {
+                        PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY
+                    } else {
                         ""
                     }
                 }
@@ -157,7 +150,6 @@ lazy_static::lazy_static! {
                 });
             }
 
-            #[cfg(feature = "virtual_display_driver")]
             map.insert(win_virtual_display::PRIVACY_MODE_IMPL, |impl_key: &str| {
                     Box::new(win_virtual_display::PrivacyModeImpl::new(impl_key))
                 });
@@ -336,7 +328,6 @@ pub fn get_supported_privacy_mode_impl() -> Vec<(&'static str, &'static str)> {
             }
         }
 
-        #[cfg(feature = "virtual_display_driver")]
         if is_installed() && crate::platform::windows::is_self_service_running() {
             vec_impls.push((
                 PRIVACY_MODE_IMPL_WIN_VIRTUAL_DISPLAY,
diff --git a/src/server/connection.rs b/src/server/connection.rs
index 6bf9602e0..9536d4e92 100644
--- a/src/server/connection.rs
+++ b/src/server/connection.rs
@@ -57,7 +57,7 @@ use std::{
 #[cfg(not(any(target_os = "android", target_os = "ios")))]
 use system_shutdown;
 
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 use crate::virtual_display_manager;
 #[cfg(not(any(target_os = "ios")))]
 use std::collections::HashSet;
@@ -1136,7 +1136,6 @@ impl Connection {
                 "is_installed".into(),
                 json!(crate::platform::is_installed()),
             );
-            #[cfg(feature = "virtual_display_driver")]
             if crate::platform::is_installed() {
                 platform_additions.extend(virtual_display_manager::get_platform_additions());
             }
@@ -1231,9 +1230,9 @@ impl Connection {
         } else {
             #[cfg(not(any(target_os = "android", target_os = "ios")))]
             {
-                #[cfg(not(all(windows, feature = "virtual_display_driver")))]
+                #[cfg(not(windows))]
                 let displays = display_service::try_get_displays();
-                #[cfg(all(windows, feature = "virtual_display_driver"))]
+                #[cfg(windows)]
                 let displays = display_service::try_get_displays_add_amyuni_headless();
                 pi.resolutions = Some(SupportedResolutions {
                     resolutions: displays
@@ -2210,7 +2209,7 @@ impl Connection {
                         let set = displays.set.iter().map(|d| *d as usize).collect::<Vec<_>>();
                         self.capture_displays(&add, &sub, &set).await;
                     }
-                    #[cfg(all(windows, feature = "virtual_display_driver"))]
+                    #[cfg(windows)]
                     Some(misc::Union::ToggleVirtualDisplay(t)) => {
                         self.toggle_virtual_display(t).await;
                     }
@@ -2598,7 +2597,7 @@ impl Connection {
         }
     }
 
-    #[cfg(all(windows, feature = "virtual_display_driver"))]
+    #[cfg(windows)]
     async fn toggle_virtual_display(&mut self, t: ToggleVirtualDisplay) {
         let make_msg = |text: String| {
             let mut msg_out = Message::new();
@@ -2655,7 +2654,7 @@ impl Connection {
                 let display_idx = d.unwrap_or(self.display_idx);
                 if let Some(display) = displays.get(display_idx) {
                     let name = display.name();
-                    #[cfg(all(windows, feature = "virtual_display_driver"))]
+                    #[cfg(windows)]
                     if let Some(_ok) =
                         virtual_display_manager::rustdesk_idd::change_resolution_if_is_virtual_display(
                             &name,
@@ -2666,7 +2665,7 @@ impl Connection {
                         return;
                     }
                     let mut record_changed = true;
-                    #[cfg(all(windows, feature = "virtual_display_driver"))]
+                    #[cfg(windows)]
                     if virtual_display_manager::amyuni_idd::is_my_display(&name) {
                         record_changed = false;
                     }
@@ -3724,7 +3723,7 @@ mod raii {
                 }
                 #[cfg(not(any(target_os = "android", target_os = "ios")))]
                 display_service::reset_resolutions();
-                #[cfg(all(windows, feature = "virtual_display_driver"))]
+                #[cfg(windows)]
                 let _ = virtual_display_manager::reset_all();
             }
             Self::check_wake_lock();
diff --git a/src/server/display_service.rs b/src/server/display_service.rs
index 386371c12..0f54188a8 100644
--- a/src/server/display_service.rs
+++ b/src/server/display_service.rs
@@ -1,7 +1,7 @@
 use super::*;
 #[cfg(target_os = "linux")]
 use crate::platform::linux::is_x11;
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 use crate::virtual_display_manager;
 #[cfg(windows)]
 use hbb_common::get_version_number;
@@ -12,7 +12,7 @@ use scrap::Display;
 
 pub const NAME: &'static str = "display";
 
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 const DUMMY_DISPLAY_SIDE_MAX_SIZE: usize = 1024;
 
 struct ChangedResolution {
@@ -158,7 +158,7 @@ fn displays_to_msg(displays: Vec<DisplayInfo>) -> Message {
     };
     pi.displays = displays.clone();
 
-    #[cfg(all(windows, feature = "virtual_display_driver"))]
+    #[cfg(windows)]
     if crate::platform::is_installed() {
         let m = crate::virtual_display_manager::get_platform_additions();
         pi.platform_additions = serde_json::to_string(&m).unwrap_or_default();
@@ -219,10 +219,10 @@ pub(super) fn get_original_resolution(
     w: usize,
     h: usize,
 ) -> MessageField<Resolution> {
-    #[cfg(all(windows, feature = "virtual_display_driver"))]
+    #[cfg(windows)]
     let is_rustdesk_virtual_display =
         crate::virtual_display_manager::rustdesk_idd::is_virtual_display(&display_name);
-    #[cfg(not(all(windows, feature = "virtual_display_driver")))]
+    #[cfg(not(windows))]
     let is_rustdesk_virtual_display = false;
     Some(if is_rustdesk_virtual_display {
         Resolution {
@@ -342,7 +342,7 @@ pub fn get_primary_2(all: &Vec<Display>) -> usize {
 }
 
 #[inline]
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 fn no_displays(displays: &Vec<Display>) -> bool {
     let display_len = displays.len();
     if display_len == 0 {
@@ -367,13 +367,13 @@ fn no_displays(displays: &Vec<Display>) -> bool {
 }
 
 #[inline]
-#[cfg(not(all(windows, feature = "virtual_display_driver")))]
+#[cfg(not(windows))]
 pub fn try_get_displays() -> ResultType<Vec<Display>> {
     Ok(Display::all()?)
 }
 
 #[inline]
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub fn try_get_displays() -> ResultType<Vec<Display>> {
     try_get_displays_(false)
 }
@@ -383,13 +383,13 @@ pub fn try_get_displays() -> ResultType<Vec<Display>> {
 // So when using amyuni idd, we only add a virtual display for headless if it is required.
 // eg. when the client is connecting.
 #[inline]
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub fn try_get_displays_add_amyuni_headless() -> ResultType<Vec<Display>> {
     try_get_displays_(true)
 }
 
 #[inline]
-#[cfg(all(windows, feature = "virtual_display_driver"))]
+#[cfg(windows)]
 pub fn try_get_displays_(add_amyuni_headless: bool) -> ResultType<Vec<Display>> {
     let mut displays = Display::all()?;