Compare commits

...
Author SHA1 Message Date
Bud cb98721da4 Update README.md 2024-12-24 17:50:07 +00:00
Bud 3e65bc8749 23H2, ITS 23H2!!!
1.10 	0x1A00 	Add HDR10 and SDR Wide Color Gamut (WCG) support - Windows 11 23H2
2024-12-22 17:11:54 +00:00
Bud 8de4f3b000 Update Submit-To-SignPath.yml 2024-12-20 00:09:37 +00:00
Bud 79810cb48d allow arm64 2024-12-19 16:16:15 +00:00
Bud a3564fbf01 Action Tweak
Action tweak
2024-12-19 13:21:28 +00:00
Bud 6c125361ac Action tweak 2024-12-19 13:19:06 +00:00
Mike Rodriguez 266b4a01c3 Merge pull request #217 from zjoasan/patch-1
Update toggle-VDD.ps1
2024-12-17 06:54:32 -08:00
Bud 0d36d2a655 workflow on pr
Added trigger workflow on pr creation to make sure no conflicting code
2024-12-17 14:54:23 +00:00
Bud 5dc87774c5 Fixed Error checking in yml
Sometimes installing dependencies dont work for some reason 🤷🏻‍♂️
2024-12-17 14:18:55 +00:00
Bud 68b92409a6 Moved rest of signpath to variables 2024-12-17 14:08:44 +00:00
Joakim Sandström 80861064e8 Update toggle-VDD.ps1
Supporting old and new driver
2024-12-17 14:50:26 +01:00
Joakim Sandström 2fd04a231b Update toggle-VDD.ps1
Changed the Friendlyname of the driver, script was OLD
2024-12-17 13:52:26 +01:00
Mike Rodriguez 1ef82c3e6a Update Submit-To-SignPath.yml 2024-12-17 04:23:22 -08:00
Bud 3895ea6b4b Upload signpath signed to github artifacts 2024-12-15 16:18:40 +00:00
Bud 13bb8cc323 json release param 2024-12-15 11:00:48 +00:00
Bud f9f95e319c Changed names to make it easier 2024-12-15 10:23:06 +00:00
Bud 22535e68de Uploaded manual workflow dispatching to signpath 2024-12-15 10:22:02 +00:00
Bud fc73feaa47 Update compile.yml 2024-12-14 10:30:46 +00:00
Bud 698c735bdf Fixed Silly mistake on action workflow 2024-12-14 10:29:10 +00:00
Bud 9cb856f645 Removed Debug 2024-12-14 09:45:15 +00:00
Bud cdc9ed24d3 Build workflow (W/o signpath)
- Without sign path to make sure build works
- Workflow on dispatch ( save on vm time)
2024-12-13 21:59:23 +00:00
Mike Rodriguez 9f90a294ee Create LICENSE 2024-12-09 23:41:29 -08:00
Bud 2f3f3c044c Update README.md 2024-12-04 23:10:15 +00:00
Bud 63c3899826 Added global refreshrates
XML function will be re-written soon

left 30hz in each one just to make it easier if users want to add per resolution
2024-12-03 21:40:00 +00:00
Bud a28ec0eb51 Pipe function Update 2024-12-03 12:54:21 +00:00
Bud d03bf38ff6 LUID with log text (In case multiple gpus) 2024-12-02 09:47:57 +00:00
Bud 4bc7e80234 Update README.md 2024-12-01 01:29:58 +00:00
Bud 25a53cab3a Update README.md 2024-12-01 01:28:44 +00:00
Mike Rodriguez 88d36bc1b5 Removed script. 2024-11-23 20:26:16 -08:00
Mike Rodriguez 68712353e3 Updated Display Preview build to reduce size and dependencies. 2024-11-23 20:14:02 -08:00
Mike Rodriguez ec5c792903 Removed requirement for FFMPEG dependency. 2024-11-23 20:07:56 -08:00
28 changed files with 438 additions and 582 deletions

No files matched your search

+141
View File
@@ -0,0 +1,141 @@
name: Virtual Display Driver Signpath Request
on:
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
configuration: [Release]
platform: [x64, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Check Chocolatey installation
run: choco --version
- name: Install Visual Studio 2022 dependencies
run: |
choco install visualstudio2022-workload-manageddesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-nativedesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-vctools -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install windowsdriverkit11 -y
if ($LASTEXITCODE -ne 0) { exit 1 }
- name: Build the driver
run: |
msbuild "Virtual Display Driver (HDR)/MTTVDD.sln" /p:Configuration=${{ matrix.configuration }} /p:Platform=${{ matrix.platform }}
- name: List build directory
run: dir "Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD"
- name: Upload built driver
id: upload_artifact
uses: actions/upload-artifact@v4
with:
name: Built-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.dll
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.inf
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\mttvdd.cat
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\vdd_settings.xml
- name: Generate release tag
id: generate_tag
run: |
$releaseTag = (Get-Date).ToString('yy.MM.dd')
echo "RELEASE_TAG=$releaseTag" >> $env:GITHUB_ENV
- name: Show generated release tag
run: |
echo "Generated Release Tag: ${{ env.RELEASE_TAG }}"
- name: Verify Built Artifacts
run: dir 'Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD'
- name: Submit signing request to SignPath
id: signpath_request
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
project-slug: '${{ vars.SIGNPATH_PROJECT_SLUG }}'
signing-policy-slug: '${{ vars.SIGNPATH_POLICY_SLUG }}'
github-artifact-id: '${{ steps.upload_artifact.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '${{ vars.SIGNPATH_OUTPUT_DIR }}'
parameters: |
Version: ${{ toJSON(matrix.configuration) }}
Release_Tag: "${{ env.RELEASE_TAG }}"
- name: Verify Signed Artifacts
run: dir '${{ vars.SIGNPATH_OUTPUT_DIR }}'
- name: Upload signed artifacts
id: upload_signed_artifacts
uses: actions/upload-artifact@v4
with:
name: Signed-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
${{ vars.SIGNPATH_OUTPUT_DIR }}\MttVDD.dll
${{ vars.SIGNPATH_OUTPUT_DIR }}\MttVDD.inf
${{ vars.SIGNPATH_OUTPUT_DIR }}\mttvdd.cat
${{ vars.SIGNPATH_OUTPUT_DIR }}\vdd_settings.xml
- name: Prepare Setup Repository
run: |
git clone https://${{ secrets.READ_REPO }}@github.com/VirtualDisplay/vdd-innosetupscript.git inno-setup
- name: Prepare Setup
run: |
copy "${{ vars.SIGNPATH_OUTPUT_DIR }}\*" inno-setup\input\
$platform = "${{ matrix.platform }}"
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace '1.0.0', '${{ env.RELEASE_TAG }}' } |
Set-Content "inno-setup\Setup.iss"
if ($platform -eq 'ARM64') {
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace 'x64compatible', 'arm64' } |
Set-Content "inno-setup\Setup.iss"
(Get-Content "inno-setup\Setup.iss") |
ForEach-Object { $_ -replace '-x64', '-arm64' } |
Set-Content "inno-setup\Setup.iss"
if (Test-Path "inno-setup\input\Companion\VDDSysTray.exe") {Remove-Item "inno-setup\input\Companion\VDDSysTray.exe"}
copy "inno-setup\input\Companion\arm64\VDDSysTray.exe" "inno-setup\input\Companion\"
}
- name: Compile Installer
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
with:
path: inno-setup\Setup.iss
options: /O+
- name: Upload Installer as artifact
uses: actions/upload-artifact@v4
with:
name: Installer-${{ matrix.configuration }}-${{ matrix.platform }}
path: inno-setup\output\*.exe
celebrate:
runs-on: ubuntu-latest
steps:
- name: Celebrate
run: |
echo "Bud is a god, also hi if you're looking at this!"
+73
View File
@@ -0,0 +1,73 @@
name: Virtual Display Driver Building
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
configuration: [Debug, Release]
platform: [x64, ARM64]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Check Chocolatey installation
run: choco --version
- name: Install Visual Studio 2022 dependencies
run: |
choco install visualstudio2022-workload-manageddesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-nativedesktop -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install visualstudio2022-workload-vctools -y
if ($LASTEXITCODE -ne 0) { exit 1 }
choco install windowsdriverkit11 -y
if ($LASTEXITCODE -ne 0) { exit 1 }
- name: Build the driver
run: |
msbuild "Virtual Display Driver (HDR)/MTTVDD.sln" /p:Configuration=${{ matrix.configuration }} /p:Platform=${{ matrix.platform }}
- name: List build directory
run: dir "Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD"
- name: Upload built driver
id: upload_artifact
uses: actions/upload-artifact@v4
with:
name: Built-Driver-${{ matrix.configuration }}-${{ matrix.platform }}
path: |
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.dll
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\MttVDD.inf
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\mttvdd.cat
Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD\vdd_settings.xml
- name: Generate release tag
id: generate_tag
run: |
$releaseTag = (Get-Date).ToString('yy.MM.dd')
echo "RELEASE_TAG=$releaseTag" >> $env:GITHUB_ENV
- name: Show generated release tag
run: |
echo "Generated Release Tag: ${{ env.RELEASE_TAG }}"
- name: Verify Built Artifacts
run: dir 'Virtual Display Driver (HDR)\${{ matrix.platform }}\${{ matrix.configuration }}\MttVDD'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

@@ -1,183 +0,0 @@
#WINDOWS
import platform
import sys
import tkinter as tk
from tkinter import ttk, messagebox
import threading
import os
import subprocess
import time
import mss
import numpy as np
import cv2
from configparser import ConfigParser
from screeninfo import get_monitors
from PIL import Image, ImageTk
from audio_manager import AudioManager
from area_selector import AreaSelector
from logging_config import setup_logging
logger = setup_logging()
class ScreenRecorderApp:
def __init__(self, root):
self.root = root
self.initialize_ffmpeg()
logger.info("THE APP WAS OPEN")
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.root.title("Display Preview")
root.geometry('1280x720')
self.config = ConfigParser()
self.config_file = 'config.ini'
self.load_config()
self.audio_manager = AudioManager()
self.audio_devices = self.audio_manager.audio_devices
if len(self.audio_devices) == 0:
messagebox.showerror("Error", "No audio devices.")
return
self.monitors = self.get_monitors()
if len(self.monitors) == 0:
messagebox.showerror("Error", "No monitors found.")
return
self.set_icon()
self.init_ui()
self.create_output_folder()
self.recording_process = None
self.running = False
self.elapsed_time = 0
self.record_area = None
self.area_selector = AreaSelector(root)
self.preview_running = False
# Start preview by default
self.preview_running = True
threading.Thread(target=self._update_preview_thread, daemon=True).start()
# Bind resizing event to dynamically adjust preview size
self.root.bind("<Configure>", self.resize_preview)
def set_icon(self):
if platform.system() == 'Windows':
self.root.iconbitmap('video.ico')
elif platform.system() == 'Linux':
icon = tk.PhotoImage(file='video.png')
self.root.iconphoto(True, icon)
def load_config(self):
if os.path.exists(self.config_file):
self.config.read(self.config_file)
else:
self.config['Settings'] = {'monitor': 0}
with open(self.config_file, 'w') as configfile:
self.config.write(configfile)
def init_ui(self):
self.monitor_label = ttk.Label(self.root, text="Monitor:")
self.monitor_label.grid(row=0, column=0, padx=10, pady=5, sticky="e")
self.monitor_combo = ttk.Combobox(self.root, values=[
f"Monitor {i+1}: ({monitor.width}x{monitor.height})"
for i, monitor in enumerate(self.monitors)
], width=25)
self.monitor_combo.grid(row=0, column=1, padx=10, pady=5, sticky="w")
self.monitor_combo.current(0)
self.monitor_combo.config(state="readonly")
self.preview_frame = ttk.Frame(self.root)
self.preview_frame.grid(row=1, column=0, columnspan=2, pady=5, padx=10, sticky="nsew")
self.preview_label = ttk.Label(self.preview_frame)
self.preview_label.pack(fill=tk.BOTH, expand=True)
# Configure resizing behavior
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(1, weight=1)
def _update_preview_thread(self):
with mss.mss() as sct:
while self.preview_running:
try:
monitor_index = self.monitor_combo.current()
if monitor_index < len(sct.monitors) - 1:
monitor = sct.monitors[monitor_index + 1]
screenshot = np.array(sct.grab(monitor))
screenshot = cv2.cvtColor(screenshot, cv2.COLOR_RGBA2RGB)
screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2RGB)
# Get current frame size
frame_width = self.preview_frame.winfo_width()
frame_height = self.preview_frame.winfo_height()
if frame_width > 0 and frame_height > 0:
# Calculate aspect-ratio-preserving dimensions
height, width, _ = screenshot.shape
scale = min(frame_width / width, frame_height / height)
new_width = int(width * scale)
new_height = int(height * scale)
# Resize screenshot while preserving aspect ratio
screenshot = cv2.resize(screenshot, (new_width, new_height), interpolation=cv2.INTER_AREA)
tk_image = ImageTk.PhotoImage(image=Image.fromarray(screenshot))
self.root.after(0, self._update_preview_label, tk_image)
time.sleep(0.03)
except tk.TclError:
break
def _update_preview_label(self, tk_image):
if self.preview_running:
self.preview_label.config(image=tk_image)
self.preview_label.image = tk_image
def resize_preview(self, event):
# Trigger a preview update on window resize
if self.preview_running:
self.preview_label.update_idletasks()
def close_preview(self):
self.preview_running = False
self.preview_label.config(image='')
self.preview_label.image = None
def on_closing(self):
self.close_preview()
self.root.quit()
self.root.destroy()
def create_output_folder(self):
self.output_folder = os.path.join(os.getcwd(), "OutputFiles")
os.makedirs(self.output_folder, exist_ok=True)
def get_monitors(self):
return get_monitors()
def initialize_ffmpeg(self):
ffmpeg_path = self.get_ffmpeg_path()
if not os.path.exists(ffmpeg_path):
logger.error("FFmpeg not found.")
messagebox.showerror("Error", "FFmpeg not found.")
sys.exit(1)
logger.info("FFmpeg was found.")
def get_ffmpeg_path(self):
base_path = os.path.dirname(os.path.abspath(__file__))
if platform.system() == 'Windows':
return os.path.join(base_path, 'ffmpeg_files', 'ffmpeg.exe')
return os.path.join(base_path, 'ffmpeg_files', 'ffmpeg')
if __name__ == "__main__":
try:
root = tk.Tk()
app = ScreenRecorderApp(root)
root.mainloop()
except Exception as e:
logger.error(f"An error occurred: {e}")
messagebox.showerror("Error", f"An unexpected error occurred: {e}")
@@ -1,44 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['DisplayPreview.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='DisplayPreview',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='DisplayPreview',
)
@@ -1,13 +0,0 @@
This script is based on a slimmed/stripped down version of LexTrack's MiniScreenRecorded.
https://github.com/lextrack/MiniScreenRecorder
To run as Python, you'll need the following dependencies:
pip install pillow mss numpy opencv-python screeninfo
These are automatically included with the build installer.
Executable built using PyInstaller.
@@ -1,81 +0,0 @@
import tkinter as tk
from tkinter import font
from PIL import ImageGrab, ImageTk
class AreaSelector:
def __init__(self, root):
self.root = root
self.record_area = None
self.rect = None
self.guide_lines = []
self.background_image = None
def select_area(self, callback):
self.callback = callback
self.root.withdraw()
screenshot = ImageGrab.grab()
self.selection_window = tk.Toplevel(self.root)
self.selection_window.attributes('-fullscreen', True)
self.selection_window.attributes('-alpha', 0.3)
self.canvas = tk.Canvas(self.selection_window, cursor="cross")
self.canvas.pack(fill=tk.BOTH, expand=True)
self.background_image = ImageTk.PhotoImage(screenshot)
self.canvas.create_image(0, 0, image=self.background_image, anchor=tk.NW)
self.canvas.bind('<ButtonPress-1>', self.on_button_press)
self.canvas.bind('<B1-Motion>', self.on_mouse_drag)
self.canvas.bind('<ButtonRelease-1>', self.on_button_release)
self.selection_window.bind('<Escape>', self.cancel_selection)
self.coord_font = font.Font(size=16)
self.coord_label = tk.Label(self.selection_window, text="", bg='black', fg='white', font=self.coord_font)
self.coord_label.place(x=10, y=10)
def on_button_press(self, event):
self.start_x = event.x
self.start_y = event.y
self.rect = None
def on_mouse_drag(self, event):
if self.rect:
self.canvas.delete(self.rect)
for line in self.guide_lines:
self.canvas.delete(line)
self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, event.x, event.y, outline='red', width=4)
self.guide_lines = [
self.canvas.create_line(event.x, 0, event.x, self.canvas.winfo_height(), fill='blue', width=4, dash=(4, 4)),
self.canvas.create_line(0, event.y, self.canvas.winfo_width(), event.y, fill='blue', width=4, dash=(4, 4))
]
width = abs(event.x - self.start_x)
height = abs(event.y - self.start_y)
self.coord_label.config(text=f"Size: {width}x{height} - Position: ({min(self.start_x, event.x)}, {min(self.start_y, event.y)})")
def on_button_release(self, event):
end_x, end_y = event.x, event.y
if self.start_x != end_x and self.start_y != end_y:
x1, y1 = min(self.start_x, end_x), min(self.start_y, end_y)
x2, y2 = max(self.start_x, end_x), max(self.start_y, end_y)
self.record_area = (x1, y1, x2, y2)
else:
self.record_area = None
self.cleanup_and_close()
def cancel_selection(self, event):
self.record_area = None
self.cleanup_and_close()
def cleanup_and_close(self):
if self.rect:
self.canvas.delete(self.rect)
for line in self.guide_lines:
self.canvas.delete(line)
self.selection_window.destroy()
self.root.deiconify()
self.callback(self.record_area)
@@ -1,89 +0,0 @@
#Windows
import locale
import platform
import subprocess
import os
import sys
from tkinter import messagebox
from venv import logger
class AudioManager:
def __init__(self):
self.audio_devices = self.get_audio_devices()
def get_audio_devices(self):
if platform.system() == 'Windows':
return self._get_windows_audio_devices()
elif platform.system() == 'Linux':
return self._get_linux_audio_devices()
else:
return []
def _get_windows_audio_devices(self):
ffmpeg_path = self._get_ffmpeg_path()
if not ffmpeg_path:
return []
cmd = [ffmpeg_path, "-list_devices", "true", "-f", "dshow", "-i", "dummy"]
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True, encoding='utf-8', errors='replace')
lines = result.stderr.splitlines()
devices = []
for line in lines:
if "audio" in line and len(line.split("\"")) > 1:
device_name = line.split("\"")[1]
normalized_name = self._normalize_audio_device_name(device_name)
devices.append(normalized_name)
if not devices:
logger.error("No active audio devices were found. Please check your audio settings.")
messagebox.showerror("Error", "No active audio devices were found. Please check your audio settings.")
return devices
except subprocess.CalledProcessError as e:
print(f"Error running FFmpeg (Audio): {e}")
return []
except FileNotFoundError:
print(f"FFmpeg (Audio) not found at {ffmpeg_path}")
return []
def _normalize_audio_device_name(self, audio_device):
system_locale = locale.getdefaultlocale()[0]
encodings_to_try = ['utf-8', 'latin-1', 'cp1252']
for encoding in encodings_to_try:
try:
audio_device = audio_device.encode(encoding).decode('utf-8')
break
except (UnicodeEncodeError, UnicodeDecodeError):
continue
return audio_device
def _get_linux_audio_devices(self):
cmd = ["pactl", "list", "sources"]
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8', errors='replace')
lines = result.stdout.splitlines()
devices = [line.split()[1] for line in lines if "Name:" in line and len(line.split()) > 1]
return devices
def _get_ffmpeg_path(self):
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.dirname(os.path.abspath(__file__))
if platform.system() == 'Windows':
ffmpeg_path = os.path.join(base_path, 'ffmpeg_files', 'ffmpeg.exe')
else: # Linux
ffmpeg_path = os.path.join(base_path, 'ffmpeg_files', 'ffmpeg')
return ffmpeg_path if os.path.exists(ffmpeg_path) else None
def refresh_devices(self):
self.audio_devices = self.get_audio_devices()
@@ -1,10 +0,0 @@
[Settings]
language = en-US
theme = light
monitor = 3
fps = 1
bitrate = 0
codec = 0
format = 0
audio = 0
@@ -1,20 +0,0 @@
import logging
from logging.handlers import RotatingFileHandler
def setup_logging():
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler('app.log', maxBytes=5*1024*1024, backupCount=5)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

+1 -1
View File
@@ -8,7 +8,7 @@
}
}
$device = get-pnpdevice -class Display -FriendlyName 'IddSampleDriver Device HDR' -ErrorAction SilentlyContinue
$device = Get-PnpDevice -Class Display -ErrorAction SilentlyContinue | Where-Object { $_.FriendlyName -eq 'IddSampleDriver Device HDR' -or $_.FriendlyName -eq 'Virtual Display Driver' }
if ($device) {
if ($device.Status -eq 'OK') {
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Virtual Display
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+53 -81
View File
@@ -1,112 +1,84 @@
# Virtual Display Driver
Based on Microsoft Indirect Display Driver Sample. This creates a virtual display in Windows that acts and functions just like a real one. It's useful for streaming, virtual reality applications, recording, headless servers, etc. The benefit over a physical display is the ability to adjust resolutions and refresh rates beyond the physical displays capabilities. For example, this would enable the ability to stream a game from your home PC using game streaming software at 240hz at 8K while owning a 60hz 1080p monitor (unrealistic, but explains the abilities well). For servers without displays, this enabled remote desktop and screen streaming to other systems as if there were a display installed.
▶️▶️▶️# Virtual Display Driver
This project creates a _virtual display_ in Windows that functions just like a physical monitor. It is particularly useful for applications such as **streaming, virtual reality, screen recording,** and **headless servers—systems** that operate without a physical display attached.
Supports emulating resolutions from **640 x 480** to **7680 x 4320 (8K)**, and refresh rates including **60hz, 75hz, 90hz, 120hz, 144hz, 165hz, 240hz, 480hz,** and **500hz.**
Unlike physical monitors, this virtual display can support resolutions and refresh rates that go beyond standard hardware limitations, offering greater flexibility for advanced setups. Furthermore, custom EDIDs can be used to simulate/emulate existing hardware displays.
This project uses the official Windows Indirect Display Driver combined with the IddCx class extension driver.
## Download Latest Version
## Download Stable Version
- [Driver Installer (Windows 10/11)](https://github.com/VirtualDisplay/Virtual-Display-Driver/releases) - Check release page for release notes.
> [!IMPORTANT]
> Please make sure you download the correct version for your operating system!
## EDID Database
- [EDID Database by Bud3699](https://edid.mikethetech.com/)
- [Windows 10 and 11 (no HDR)](https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/23.10.20.2)
- [Windows 11 23H2+ (HDR)](https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/23.12.2HDR)
You can use this database to load custom edid's into the driver! Or just general edid usage :)
## Download Beta
- [Universal Driver - 24.10.27 (Windows 10/11)](https://github.com/itsmikethetech/Virtual-Display-Driver/releases/tag/24.10.27) - Added more plus optimisations
[Edid database by bud (beta only - for custom edid) ](https://edid.mikethetech.com/)
## Installation
### Release Instructions
- Step 1: Download the Installer
- You can download the insaller directly from the [Releases](https://github.com/VirtualDisplay/Virtual-Display-Driver/releases) page.
1. Download the latest version from the above or the website, and extract the contents to a folder.
2. Copy the `\IddSampleDriver\` folder and its contents to `C:\IddSampleDriver\` before installing the driver **(important!)**.
3. Right click and run the *.bat file **as an Administrator** to add the driver certificate as a trusted root certificate.
4. Don't install the inf. Open device manager, click on any device, then click on the "Action" menu and click "Add Legacy Hardware".
5. Select "Add hardware from a list (Advanced)" and then select Display adapters.
6. Click "Have Disk..." and click the "Browse..." button. Navigate to the extracted files and select the inf file.
7. You are done! Go to display settings to customize the resolution of the additional displays. These displays show up in Sunshine, your Oculus or VR settings, and should be able to be streamed from.
8. You can enable/disable the display adapter to toggle the monitors.
- Step 2: Run the Installer
- Download and run the installer.
- Follow the on-screen instructions to complete the installation.
**Ps.** Make sure that `options.txt` is accessible for the system at `C:\IddSampleDriver\options.txt` or the installation will fail.
- Step 3: Verify the Installation (Optional)
- Check if the Virtual Display Driver is correctly installed by running the following:
- **Device Manager:** Check "Device Manager" under "Display Adapters."
- **Settings:** Check display settings under system settings and see if the virtual displays show.
---
Manual installation can be found in the wiki
### Beta Release Instructions
## 🤔 Comparison with other IDDs
1. Download the beta version and extract the contents to a folder.
2. Copy the `\VirtualDisplayDriver\` folder and its contents to `C:\VirtualDisplayDriver\` before installing the driver **(important!)**.
3. Right click and run the *.bat file **as an Administrator** to add the driver certificate as a trusted root certificate.
4. Don't install the inf. Open device manager, click on any device, then click on the "Action" menu and click "Add Legacy Hardware".
5. Select "Add hardware from a list (Advanced)" and then select Display adapters.
6. Click "Have Disk..." and click the "Browse..." button. Navigate to the extracted files and select the inf file.
7. You are done! Go to display settings to customize the resolution of the additional displays. These displays show up in Sunshine, your Oculus or VR settings, and should be able to be streamed from.
8. You can enable/disable the display adapter to toggle the monitors.
The table below shows a comparison with other popular Indirect Display Driver
projects.
![Untitled-6](https://github.com/user-attachments/assets/98ccb915-5a94-42f9-818b-213ceef4c3ac)
## Easy Uninstall
¹ ARM64 Support in Windows 11 24H2 or later may require test signing be enabled.
1. Open device manager
2. Locate Display Adapters
3. Right click on IddSampleDriver, choose "Uninstall device"
4. There is a new popup window, in there click Attempt to remove driver for this device.
## HDR Support Now Available for Windows 11 23H2+
## Manual/Forced Uninstall
### Installation Video
Next instructions are for those cases where the device is removed from the system, but driver stil remains. This happens when there is a connection to the device while trying to remove the drivers. To
remedy this, there is a a few tricks built into windows. So here goes:
[![vidgit2](https://github.com/user-attachments/assets/f9135092-55dc-4311-bc9a-ebbbfbe60a85)](https://youtu.be/Oz_cfbfUx0E)
1. Open up a powershell terminal and input this:
2. ```pnputil /enum-drivers```
3. Locate iddsampledriver.inf, there might be multiple pages of text. Make a note of the "published name", it's often unique for your system, but might look like "oem139.inf"
4. ```pnputil /delete-driver oem139.inf```
5. (If you still get multiple displays after uninstall, try to repeat uninstall procedure in safemode.)
## More Videos and Resources
- 24.12.24 (Stable): MikeTheTech: [How to install the New Virtual Display Driver](https://youtu.be/Oz_cfbfUx0E)
- 24.12.24 (Stable): MikeTheTech: [How to manually install the New Virtual Display Driver](https://youtu.be/sM9rNJWssAI)
- 24.12.24 (Stable): Bud3699: [How to configure the VDD using the new Companion App](https://youtu.be/p_gfjE_cwjk)
- 24.10.27 (Beta): [MikeTheTech: How to install a virtual display](https://youtu.be/byfBWDnToYk "How to install a virtual display")
## HDR Support Now Available for Windows 11 22H2+
![Powerpoint](https://github.com/user-attachments/assets/9ac05776-36e1-4ba1-ac52-3f189dbd7730)
### Videos
## 🤝 Sponsors
[![thumbnail2023](https://github.com/itsmikethetech/Virtual-Display-Driver/assets/25166211/1a64c390-5d8a-420f-8bb9-4642349fc132)](https://youtu.be/nNWpbRUPkn4 "How to install a virtual display")
<table>
<tr>
<td><img src="https://github.com/user-attachments/assets/ca93d971-67dc-41dd-b945-ab4f372ea72a" /></td>
<td>Free code signing on Windows provided by <a href="https://signpath.io">SignPath.io</a>, certificate by <a href="https://signpath.org">SignPath Foundation</a></td>
</tr>
</table>
[Previous Video: How to install a virtual display](https://youtu.be/byfBWDnToYk "How to install a virtual display")
## Developers
### Screenshots:
![image](https://github.com/itsmikethetech/Virtual-Display-Driver/assets/25166211/0f1dfed6-c9ac-4cb6-92cf-7d9ab2ac0c66)
![image](https://github.com/itsmikethetech/Virtual-Display-Driver/assets/25166211/5cb8ce08-890f-4bc1-a1a6-34f22e103699)
![image](https://github.com/itsmikethetech/Virtual-Display-Driver/assets/25166211/02af86f2-b896-4265-9174-b17c9a1aeab7)
## License
MIT and CC0 or Public Domain (for changes I made, please consult Microsoft for their license), choose the least restrictive option.
## Disclaimer:
This software is provided "AS IS" with NO IMPLICIT OR EXPLICIT warranty. It's worth noting that while this software functioned without issues on my system, there is no guarantee that it will not impact your computer. It operates in User Mode, which reduces the likelihood of causing system instability, such as the Blue Screen of Death. However, exercise caution when using this software.
- Shoutout to **[MikeTheTech](https://github.com/itsmikethetech)** Project Boss man, owner and programmer!
- Shoutout to **[Bud](https://github.com/bud3699)** For a ton of features, companion & installer work
- Shoutout to **[zjoasan](https://github.com/zjoasan)** For scripts and part of installer
## Acknowledgements
Shoutout to **[Bud](https://github.com/bud3699)** and **[zjoasan](https://github.com/zjoasan)** for jumping on the team and helping with not just support, but lots of great new features!
Shoutout to **[Roshkins](https://github.com/roshkins/IddSampleDriver)** for the original repo.
Shoutout to **[Baloukj](https://github.com/baloukj/IddSampleDriver)** for the 8-bit / 10-bit support. (Also, first to push the new Microsoft Driver public!)
Shoutout to **[Anakngtokwa](https://github.com/Anakngtokwa)** for assisting with finding driver sources.
**[Microsoft](https://github.com/microsoft/Windows-driver-samples/tree/master/video/IndirectDisplay)** Indirect Display Driver/Sample (Driver code)
Thanks to **[AKATrevorJay](https://github.com/akatrevorjay/edid-generator)** for the hi-res EDID.
Shoutout to **[LexTrack](https://github.com/lextrack/)** for the MiniScreenRecorder script.
- Shoutout to **[Roshkins](https://github.com/roshkins/IddSampleDriver)** for the original repo.
- Shoutout to **[Baloukj](https://github.com/baloukj/IddSampleDriver)** for the 8-bit / 10-bit support. (Also, first to push the new Microsoft Driver public!)
- Shoutout to **[Anakngtokwa](https://github.com/Anakngtokwa)** for assisting with finding driver sources.
- **[Microsoft](https://github.com/microsoft/Windows-driver-samples/tree/master/video/IndirectDisplay)** Indirect Display Driver/Sample (Driver code)
- Thanks to **[AKATrevorJay](https://github.com/akatrevorjay/edid-generator)** for the hi-res EDID.
- Shoutout to **[LexTrack](https://github.com/lextrack/)** for the MiniScreenRecorder script.
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=itsmikethetech/Virtual-Display-Driver&type=Date)](https://star-history.com/#itsmikethetech/Virtual-Display-Driver&Date)
[![Star History Chart](https://api.star-history.com/svg?repos=VirtualDisplay/Virtual-Display-Driver&type=Date)](https://star-history.com/#VirtualDisplay/Virtual-Display-Driver&Date)
## Disclaimer:
This software is provided "AS IS" with NO IMPLICIT OR EXPLICIT warranty. It's worth noting that while this software functioned without issues on our systems, there is no guarantee that it will not impact your computer. It operates in User Mode(Session0), which reduces the likelihood of causing system instability, such as the Blue Screen of Death. However, exercise caution when using this software.
+140 -35
View File
@@ -38,6 +38,7 @@ Environment:
#include <string>
#include <cstdlib>
#include <map>
#include <set>
@@ -332,6 +333,9 @@ void vddlog(const char* type, const char* message) {
case 't':
logType = "TESTING";
break;
case 'c':
logType = "COMPANION";
break;
default:
logType = "UNKNOWN";
break;
@@ -783,6 +787,16 @@ bool UpdateXmlDisplayCountSetting(int displayCount) {
}
LUID getSetAdapterLuid() {
AdapterOption& adapterOption = Options.Adapter;
if (!adapterOption.hasTargetAdapter) {
vddlog("e","No Gpu Found/Selected");
}
return adapterOption.adapterLuid;
}
void GetGpuInfo()
{
@@ -793,20 +807,55 @@ void GetGpuInfo()
return;
}
string utf8_desc;
try {
utf8_desc = WStringToString(adapterOption.target_name);
string utf8_desc = WStringToString(adapterOption.target_name);
LUID luid = getSetAdapterLuid();
string logtext = "ASSIGNED GPU: " + utf8_desc +
" (LUID: " + std::to_string(luid.LowPart) + "-" + std::to_string(luid.HighPart) + ")";
vddlog("i", logtext.c_str());
}
catch (const exception& e) {
vddlog("e", ("Conversion error: " + string(e.what())).c_str());
vddlog("e", ("Error: " + string(e.what())).c_str());
}
}
void logAvailableGPUs() {
vector<GPUInfo> gpus;
ComPtr<IDXGIFactory1> factory;
if (!SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory)))) {
return;
}
string logtext = "ASSIGNED GPU: " + utf8_desc;
vddlog("i", logtext.c_str());
for (UINT i = 0;; i++) {
ComPtr<IDXGIAdapter> adapter;
if (!SUCCEEDED(factory->EnumAdapters(i, &adapter))) {
break;
}
DXGI_ADAPTER_DESC desc;
if (!SUCCEEDED(adapter->GetDesc(&desc))) {
continue;
}
GPUInfo info{ desc.Description, adapter, desc };
gpus.push_back(info);
}
for (const auto& gpu : gpus) {
wstring logMessage = L"GPU Name: ";
logMessage += gpu.desc.Description;
wstring memorySize = L" Memory: ";
memorySize += std::to_wstring(gpu.desc.DedicatedVideoMemory / (1024 * 1024)) + L" MB";
wstring logText = logMessage + memorySize;
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, logText.c_str(), -1, nullptr, 0, nullptr, nullptr);
if (bufferSize > 0) {
std::string logTextA(bufferSize - 1, '\0');
WideCharToMultiByte(CP_UTF8, 0, logText.c_str(), -1, &logTextA[0], bufferSize, nullptr, nullptr);
vddlog("c", logTextA.c_str());
}
}
}
void ReloadDriver(HANDLE hPipe) {
auto* pContext = WdfObjectGet_IndirectDeviceContextWrapper(hPipe);
if (pContext && pContext->pContext) {
@@ -830,7 +879,7 @@ void HandleClient(HANDLE hPipe) {
WideCharToMultiByte(CP_UTF8, 0, bufferwstr.c_str(), -1, &bufferstr[0], bufferSize, nullptr, nullptr);
vddlog("p", bufferstr.c_str());
if (wcsncmp(buffer, L"RELOAD_DRIVER", 13) == 0) {
vddlog("i", "Reloading the driver");
vddlog("c", "Reloading the driver");
ReloadDriver(hPipe);
}
@@ -839,13 +888,13 @@ void HandleClient(HANDLE hPipe) {
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"debuglogging");
debugLogs = true;
vddlog("i", "Pipe debugging enabled");
vddlog("c", "Pipe debugging enabled");
vddlog("d", "Debug Logs Enabled");
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"debuglogging");
debugLogs = false;
vddlog("i", "Debugging disabled");
vddlog("c", "Debugging disabled");
}
}
else if (wcsncmp(buffer, L"LOGGING", 7) == 0) {
@@ -853,24 +902,24 @@ void HandleClient(HANDLE hPipe) {
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"logging");
logsEnabled = true;
vddlog("i", "Logging Enabled");
vddlog("c", "Logging Enabled");
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"logging");
logsEnabled = false;
vddlog("i", "Logging disabled"); // We can keep this here just to make it delete the logs on disable
vddlog("c", "Logging disabled"); // We can keep this here just to make it delete the logs on disable
}
}
else if (wcsncmp(buffer, L"HDRPLUS", 7) == 0) {
wchar_t* param = buffer + 8;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"HDRPlus");
vddlog("i", "HDR+ Enabled");
vddlog("c", "HDR+ Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"HDRPlus");
vddlog("i", "HDR+ Disabled");
vddlog("c", "HDR+ Disabled");
ReloadDriver(hPipe);
}
}
@@ -878,12 +927,12 @@ void HandleClient(HANDLE hPipe) {
wchar_t* param = buffer + 6;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"SDR10bit");
vddlog("i", "SDR 10 Bit Enabled");
vddlog("c", "SDR 10 Bit Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"SDR10bit");
vddlog("i", "SDR 10 Bit Disabled");
vddlog("c", "SDR 10 Bit Disabled");
ReloadDriver(hPipe);
}
}
@@ -891,12 +940,12 @@ void HandleClient(HANDLE hPipe) {
wchar_t* param = buffer + 11;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"CustomEdid");
vddlog("i", "Custom Edid Enabled");
vddlog("c", "Custom Edid Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"CustomEdid");
vddlog("i", "Custom Edid Disabled");
vddlog("c", "Custom Edid Disabled");
ReloadDriver(hPipe);
}
}
@@ -904,12 +953,12 @@ void HandleClient(HANDLE hPipe) {
wchar_t* param = buffer + 13;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"PreventSpoof");
vddlog("i", "Prevent Spoof Enabled");
vddlog("c", "Prevent Spoof Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"PreventSpoof");
vddlog("i", "Prevent Spoof Disabled");
vddlog("c", "Prevent Spoof Disabled");
ReloadDriver(hPipe);
}
}
@@ -917,12 +966,12 @@ void HandleClient(HANDLE hPipe) {
wchar_t* param = buffer + 12;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"EdidCeaOverride");
vddlog("i", "Cea override Enabled");
vddlog("c", "Cea override Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"EdidCeaOverride");
vddlog("i", "Cea override Disabled");
vddlog("c", "Cea override Disabled");
ReloadDriver(hPipe);
}
}
@@ -930,29 +979,35 @@ void HandleClient(HANDLE hPipe) {
wchar_t* param = buffer + 15;
if (wcsncmp(param, L"true", 4) == 0) {
UpdateXmlToggleSetting(true, L"HardwareCursor");
vddlog("i", "Hardware Cursor Enabled");
vddlog("c", "Hardware Cursor Enabled");
ReloadDriver(hPipe);
}
else if (wcsncmp(param, L"false", 5) == 0) {
UpdateXmlToggleSetting(false, L"HardwareCursor");
vddlog("i", "Hardware Cursor Disabled");
vddlog("c", "Hardware Cursor Disabled");
ReloadDriver(hPipe);
}
}
else if (wcsncmp(buffer, L"D3DDEVICEGPU", 12) == 0) {
vddlog("i", "Retrieving D3D GPU (This information may be inaccurate without reloading the driver first)");
vddlog("c", "Retrieving D3D GPU (This information may be inaccurate without reloading the driver first)");
InitializeD3DDeviceAndLogGPU();
vddlog("i", "Rerieved D3D GPU");
vddlog("c", "Retrieved D3D GPU");
}
else if (wcsncmp(buffer, L"IDDCXVERSION", 12) == 0) {
vddlog("i", "Logging iddcx version");
vddlog("c", "Logging iddcx version");
LogIddCxVersion();
}
else if (wcsncmp(buffer, L"GETASSIGNEDGPU", 14) == 0) {
vddlog("i", "Retrieving Assigned GPU");
vddlog("c", "Retrieving Assigned GPU");
GetGpuInfo();
vddlog("i", "Rerieved Assigned GPU");
}
vddlog("c", "Retrieved Assigned GPU");
}
else if (wcsncmp(buffer, L"GETALLGPUS", 10) == 0) {
vddlog("c", "Logging all GPUs");
vddlog("i", "Any GPUs which show twice but you only have one, will most likely be the GPU the driver is attached to");
logAvailableGPUs();
vddlog("c", "Logged all GPUs");
}
else if (wcsncmp(buffer, L"SETGPU", 6) == 0) {
std::wstring gpuName = buffer + 7;
gpuName = gpuName.substr(1, gpuName.size() - 2);
@@ -961,9 +1016,9 @@ void HandleClient(HANDLE hPipe) {
std::string gpuNameNarrow(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, gpuName.c_str(), static_cast<int>(gpuName.length()), &gpuNameNarrow[0], size_needed, nullptr, nullptr);
vddlog("i", ("Setting GPU to: " + gpuNameNarrow).c_str());
vddlog("c", ("Setting GPU to: " + gpuNameNarrow).c_str());
if (UpdateXmlGpuSetting(gpuName.c_str())) {
vddlog("i", "Gpu Changed, Restarting Driver");
vddlog("c", "Gpu Changed, Restarting Driver");
}
else {
vddlog("e", "Failed to update GPU setting in XML. Restarting anyway");
@@ -977,10 +1032,10 @@ void HandleClient(HANDLE hPipe) {
swscanf_s(buffer + 15, L"%d", &newDisplayCount);
std::wstring displayLog = L"Setting display count to " + std::to_wstring(newDisplayCount);
vddlog("i", WStringToString(displayLog).c_str());
vddlog("c", WStringToString(displayLog).c_str());
if (UpdateXmlDisplayCountSetting(newDisplayCount)){
vddlog("i", "Display Count Changed, Restarting Driver");
vddlog("c", "Display Count Changed, Restarting Driver");
}
else {
vddlog("e", "Failed to update display count setting in XML. Restarting anyway");
@@ -1241,6 +1296,8 @@ void loadSettings() {
vector<tuple<int, int, int, int>> res;
wstring gpuFriendlyName;
UINT monitorcount = 1;
set<tuple<int, int>> resolutions;
vector<int> globalRefreshRates;
while (S_OK == (hr = pReader->Read(&nodeType))) {
switch (nodeType) {
@@ -1277,6 +1334,7 @@ void loadSettings() {
if (height.empty()) {
height = L"600";
}
resolutions.insert(make_tuple(stoi(width), stoi(height)));
}
else if (currentElement == L"refresh_rate") {
refreshRate = wstring(pwszValue, cwchValue);
@@ -1291,10 +1349,57 @@ void loadSettings() {
ss << "Added: " << stoi(width) << "x" << stoi(height) << " @ " << vsync_num << "/" << vsync_den << "Hz";
vddlog("d", ss.str().c_str());
}
else if (currentElement == L"g_refresh_rate") {
globalRefreshRates.push_back(stoi(wstring(pwszValue, cwchValue)));
}
break;
}
}
/*
* This is for res testing, stores each resolution then iterates through each global adding a res for each one
*
for (const auto& resTuple : resolutions) {
stringstream ss;
ss << get<0>(resTuple) << "x" << get<1>(resTuple);
vddlog("t", ss.str().c_str());
}
for (const auto& globalRate : globalRefreshRates) {
stringstream ss;
ss << globalRate << " Hz";
vddlog("t", ss.str().c_str());
}
*/
for (int globalRate : globalRefreshRates) {
for (const auto& resTuple : resolutions) {
int global_width = get<0>(resTuple);
int global_height = get<1>(resTuple);
int vsync_num, vsync_den;
float_to_vsync(static_cast<float>(globalRate), vsync_num, vsync_den);
res.push_back(make_tuple(global_width, global_height, vsync_num, vsync_den));
}
}
/*
* logging all resolutions after added global
*
for (const auto& tup : res) {
stringstream ss;
ss << "("
<< get<0>(tup) << ", "
<< get<1>(tup) << ", "
<< get<2>(tup) << ", "
<< get<3>(tup) << ")";
vddlog("t", ss.str().c_str());
}
*/
numVirtualDisplays = monitorcount;
gpuname = gpuFriendlyName;
monitorModes = res;
@@ -1385,10 +1490,10 @@ void loadSettings() {
int vsync_num, vsync_den;
float_to_vsync(refreshRate, vsync_num, vsync_den);
stringstream ss;
stringstream ss;
res.push_back(make_tuple(width, height, vsync_num, vsync_den));
stringstream ss;
ss << "Resolution: " << width << "x" << height << " @ " << vsync_num << "/" << vsync_den << "Hz";
vddlog("d", ss.str().c_str());
}
+9 -25
View File
@@ -6,56 +6,40 @@
<gpu>
<friendlyname>default</friendlyname>
</gpu>
<global>
<!--These are global refreshrates, any you add in here, will be replicated to all resolutions-->
<g_refresh_rate>60</g_refresh_rate>
<g_refresh_rate>90</g_refresh_rate>
<g_refresh_rate>120</g_refresh_rate>
<g_refresh_rate>144</g_refresh_rate>
<g_refresh_rate>165</g_refresh_rate>
<g_refresh_rate>244</g_refresh_rate>
</global>
<resolutions>
<resolution>
<width>800</width>
<height>600</height>
<refresh_rate>30</refresh_rate>
<refresh_rate>60</refresh_rate>
<refresh_rate>90</refresh_rate>
<refresh_rate>120</refresh_rate>
<refresh_rate>144</refresh_rate>
<refresh_rate>165</refresh_rate>
</resolution>
<resolution>
<width>1366</width>
<height>768</height>
<refresh_rate>30</refresh_rate>
<refresh_rate>60</refresh_rate>
<refresh_rate>90</refresh_rate>
<refresh_rate>120</refresh_rate>
<refresh_rate>144</refresh_rate>
<refresh_rate>165</refresh_rate>
</resolution>
<resolution>
<width>1920</width>
<height>1080</height>
<refresh_rate>30</refresh_rate>
<refresh_rate>60</refresh_rate>
<refresh_rate>90</refresh_rate>
<refresh_rate>120</refresh_rate>
<refresh_rate>144</refresh_rate>
<refresh_rate>165</refresh_rate>
</resolution>
<resolution>
<width>2560</width>
<height>1440</height>
<refresh_rate>30</refresh_rate>
<refresh_rate>60</refresh_rate>
<refresh_rate>90</refresh_rate>
<refresh_rate>120</refresh_rate>
<refresh_rate>144</refresh_rate>
<refresh_rate>165</refresh_rate>
</resolution>
<resolution>
<width>3840</width>
<height>2160</height>
<refresh_rate>30</refresh_rate>
<refresh_rate>60</refresh_rate>
<refresh_rate>90</refresh_rate>
<refresh_rate>120</refresh_rate>
<refresh_rate>144</refresh_rate>
<refresh_rate>165</refresh_rate>
</resolution>