Skip to content

fix: add explicit target mode fallback for non-standard resolutions (#594)#595

Merged
qiin2333 merged 5 commits intomasterfrom
fix/explicit-target-mode-fallback
Apr 16, 2026
Merged

fix: add explicit target mode fallback for non-standard resolutions (#594)#595
qiin2333 merged 5 commits intomasterfrom
fix/explicit-target-mode-fallback

Conversation

@qiin2333
Copy link
Copy Markdown
Collaborator

Problem

When streaming to devices with non-standard resolutions like 2560x1600 (16:10 aspect ratio), the SetDisplayConfig API returns ERROR_GEN_FAILURE because Windows CCD (Connecting and Configuring Displays) cannot find a valid source-to-target mode mapping in its topology database for newly created virtual display paths.

The failure occurs in set_display_modes() in device_modes.cpp:

  1. First attempt (SDC_ALLOW_CHANGES): Windows adjusts the mode to something else (e.g., 2560x1440), fuzzy compare detects mismatch
  2. Second attempt (strict mode): SetDisplayConfig returns ERROR_GEN_FAILURE because the CCD database has no mapping for the non-standard resolution

Standard resolutions like 2560x1440 work because Windows has built-in mode matching support for common 16:9 modes.

Root Cause

The current code clears the targetModeInfoIdx and desktopModeInfoIdx in the path, telling Windows to automatically match source mode to target mode. For newly created VDD paths with non-standard resolutions (especially when the CCD topology was itself just created via fallback), Windows' automatic mode matching algorithm fails.

Solution

Add a third fallback attempt in set_display_modes() via a new do_set_modes_with_explicit_target() function that:

  • Does NOT clear the target mode index
  • Instead, directly modifies the existing target mode entry in-place with the desired resolution and signal parameters (activeSize, totalSize, vSyncFreq, hSyncFreq, pixelRate)
  • Also updates the desktop image info if present

This bypasses Windows CCD's automatic mode matching entirely by providing a complete, self-consistent display configuration.

Impact

  • Zero impact on existing working environments: The new fallback only triggers when both original attempts fail
  • Fixes non-standard resolution support: Resolutions like 2560x1600, 1920x1200, etc. on virtual displays
  • Single file change: Only device_modes.cpp is modified

Closes #594

…594)

When Windows CCD mode matching fails for non-standard resolutions
(e.g. 16:10 like 2560x1600) on newly created virtual display paths,
the SetDisplayConfig API returns ERROR_GEN_FAILURE because it cannot
find a valid source-to-target mode mapping in its topology database.

This adds a third fallback attempt in set_display_modes() that
explicitly sets target mode parameters (activeSize, totalSize,
vSyncFreq, hSyncFreq, pixelRate) in-place instead of clearing
the target mode index and relying on Windows' automatic matching.

The fallback only triggers when both existing attempts (with and
without SDC_ALLOW_CHANGES) fail, so it has zero impact on
environments where mode setting already works correctly.

Closes #594
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2a8bcb42-4021-44bb-86d5-ac043ac2d481

📥 Commits

Reviewing files that changed from the base of the PR and between 074de9e and 3df5301.

📒 Files selected for processing (1)
  • src/platform/windows/display_device/device_modes.cpp
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Windows
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/platform/windows/display_device/device_modes.cpp
src/platform/**

⚙️ CodeRabbit configuration file

src/platform/**: 平台抽象层代码(Windows/Linux/macOS)。确保各平台实现一致, 注意 Windows API 调用的错误处理和资源释放。

Files:

  • src/platform/windows/display_device/device_modes.cpp
🔇 Additional comments (2)
src/platform/windows/display_device/device_modes.cpp (2)

201-302: 新增的显式目标模式回退逻辑实现正确,已修复先前提出的问题。

代码结构合理:

  1. 在访问 modes[target_idx] 前进行边界和类型校验(252-262 行),避免了先前提出的"部分更新导致陈旧 desktop-image 条目"的问题
  2. 第 285 行调用 w_utils::set_desktop_index(*path, boost::none) 清除桌面图像索引,解决了先前提出的 SDC_VIRTUAL_MODE_AWARE 下 topology 不一致问题
  3. 第 268 行对 denominator 为零的防御性处理是好的实践

信号参数计算(270-279 行)将 totalSize 设为 activeSize(无消隐区间),对于 VDD 虚拟显示路径是合理的简化,且内部保持一致。


396-447: 控制流重构正确,已解决先前提出的"回退链无法覆盖首次失败场景"的问题。

改进后的逻辑:

  1. 第 396 行捕获首次尝试结果,而非立即返回
  2. 第 415-417 行仅在首次成功 验证通过时才短路返回
  3. 第 430-435 行的严格模式重试和第 442-447 行的显式目标回退现在能够覆盖:
    • 首次 SetDisplayConfig 返回 ERROR_GEN_FAILURE 的场景(PR #594 的主要问题)
    • 调用成功但结果不匹配的场景

这与 settings.cpp 中调用者的期望一致——set_display_modes() 返回 true 表示模式已成功应用并通过验证。


Summary by CodeRabbit

  • Bug 修复
    • 提升 Windows 下显示配置应用的稳健性,优化多显示器场景中显示模式的匹配与应用流程。
    • 引入更严格的重试与显式目标回退策略:在常规应用或验证失败时依次尝试不同策略以提高配置成功率。
    • 改善设置后验证与失败处理,减少不必要回滚,提升显示设置应用的可预测性与用户体验。

Walkthrough

在 set_display_modes 中新增更严格的重试与显式目标回退路径:首次设置后进行验证;若失败则切换 allow_changes 再试;仍不匹配时重查询当前拓扑、就地更新目标 mode 的 targetVideoSignalInfo、清除桌面图像索引并以 SDC_USE_SUPPLIED_DISPLAY_CONFIG 调用 SetDisplayConfig 并再次验证,否则回滚失败。

Changes

Cohort / File(s) Summary
Windows 显示模式设置与回退
src/platform/windows/display_device/device_modes.cpp
新增 do_set_modes_with_explicit_target(modes):重查询活动显示配置、在原位更新受影响路径的源分辨率与 DISPLAYCONFIG_MODE_INFO_TYPE_TARGETtargetVideoSignalInfo(active/total 尺寸、vSync/hSync 频率、像素率、扫描类型)、清除 desktop image index,并以 `SetDisplayConfig(..., SDC_APPLY

Sequence Diagram(s)

sequenceDiagram
    participant Manager as ModeManager
    participant OS as WindowsDisplaySubsystem
    participant Topo as ActiveTopologyStore
    Manager->>OS: do_set_modes(modes, allow_changes)
    alt first attempt OK & verified
        OS-->>Manager: ERROR_SUCCESS (verified)
    else
        Manager->>OS: do_set_modes(modes, !allow_changes)
        alt second attempt OK & verified
            OS-->>Manager: ERROR_SUCCESS (verified)
        else
            Manager->>OS: QueryDisplayConfig()
            OS-->>Topo: return current paths & mode infos
            Topo-->>Manager: current topology
            Manager->>Topo: modify source resolution & targetMode.targetVideoSignalInfo
            Manager->>Topo: clear desktop image index
            Manager->>OS: SetDisplayConfig(modified topology, SDC_USE_SUPPLIED_DISPLAY_CONFIG...)
            alt ERROR_SUCCESS & verified
                OS-->>Manager: success (verified)
            else
                OS-->>Manager: failure -> rollback/fail
            end
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题清晰准确地反映了PR的主要改动:为非标准分辨率添加显式目标模式回退机制,直接关联了issues #594
Description check ✅ Passed 描述详细阐述了问题、根本原因和解决方案,与changeset紧密相关,包括影响范围的清晰说明。
Linked Issues check ✅ Passed PR实现了issue #594的所有关键需求:添加了新的do_set_modes_with_explicit_target()回退机制,处理非标准分辨率,保留现有行为,避免ERROR_GEN_FAILURE。
Out of Scope Changes check ✅ Passed 所有改动都限制在device_modes.cpp文件内,直接针对issue #594的需求,没有发现超出范围的改动。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/explicit-target-mode-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/platform/windows/display_device/device_modes.cpp (1)

252-275: 建议在 target_idx 无效时添加调试日志

target_idx 无效或超出范围时,代码会静默跳过目标模式更新。考虑到这是一个用于调试非标准分辨率问题的回退路径,添加日志可以帮助诊断回退失败的原因。

💡 建议添加调试日志
         const UINT32 target_idx { path->targetInfo.targetModeInfoIdx };
         if (target_idx != DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID && target_idx < display_data->modes.size()) {
           auto &target_mode_info = display_data->modes[target_idx];
           if (target_mode_info.infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET) {
             // ... existing code ...
+          } else {
+            BOOST_LOG(debug) << "Target mode info type mismatch for device: " << device_id;
           }
+        } else {
+          BOOST_LOG(debug) << "Invalid target mode index for device: " << device_id << ", idx=" << target_idx;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/windows/display_device/device_modes.cpp` around lines 252 - 275,
当 target_idx 等于 DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID 或者 target_idx >=
display_data->modes.size() 时当前静默跳过目标模式更新;在这条分支处(在对 target_idx 的 if 判断外或其 else
分支里)添加一条调试日志,记录 target_idx 值、display_data->modes.size() 以及相关 mode(如
mode.resolution.width/height 和
mode.refresh_rate.numerator/denominator)的信息,以便追踪为何未应用目标模式(引用符号:target_idx、DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID、display_data->modes、mode、path->targetInfo.targetModeInfoIdx、target_mode_info)。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/platform/windows/display_device/device_modes.cpp`:
- Around line 252-275: 当 target_idx 等于
DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID 或者 target_idx >=
display_data->modes.size() 时当前静默跳过目标模式更新;在这条分支处(在对 target_idx 的 if 判断外或其 else
分支里)添加一条调试日志,记录 target_idx 值、display_data->modes.size() 以及相关 mode(如
mode.resolution.width/height 和
mode.refresh_rate.numerator/denominator)的信息,以便追踪为何未应用目标模式(引用符号:target_idx、DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID、display_data->modes、mode、path->targetInfo.targetModeInfoIdx、target_mode_info)。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f28aef29-aa7b-4215-a010-562a132e4865

📥 Commits

Reviewing files that changed from the base of the PR and between 7f11979 and 2d4dd93.

📒 Files selected for processing (1)
  • src/platform/windows/display_device/device_modes.cpp
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/platform/windows/display_device/device_modes.cpp
src/platform/**

⚙️ CodeRabbit configuration file

src/platform/**: 平台抽象层代码(Windows/Linux/macOS)。确保各平台实现一致, 注意 Windows API 调用的错误处理和资源释放。

Files:

  • src/platform/windows/display_device/device_modes.cpp
🔇 Additional comments (4)
src/platform/windows/display_device/device_modes.cpp (4)

277-290: 桌面图像信息更新逻辑正确

正确地只更新了 rightbottom 字段(lefttop 保持为 0),这符合 Windows RECT 结构的原点坐标惯例。


443-453: 控制流变更正确,遵循现有模式

新增的回退逻辑正确地遵循了函数中已建立的模式:

  1. 仅在推荐模式和严格模式都失败后才尝试
  2. 在尝试前记录信息日志
  3. 成功后验证模式是否匹配
  4. 失败时继续执行原有的恢复逻辑

这种渐进式回退策略确保了现有工作场景不受影响。


299-301: 日志级别使用合理

这里使用 warning 而非 error 级别是合理的,因为这是回退路径,失败后还会尝试恢复原始模式。这与主路径 do_set_modes 中使用 error 级别形成了适当的区分。


262-271: 这些信号参数计算是 Windows 虚拟显示驱动 (VDD) 的标准做法,与 Microsoft 官方 IddCx 示例代码一致,无需进一步验证。设置 activeSizetotalSize 相同(无消隐间隔),以及使用 hSyncFreq = vSync * HeightpixelRate = vSync * Width * Height / Denominator 的公式,都是 VDD 实现的规范方式。

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/windows/display_device/device_modes.cpp`:
- Around line 429-438: The code currently returns false immediately when
do_set_modes(modes, allow_changes) fails (e.g., ERROR_GEN_FAILURE), so the later
fallback do_set_modes_with_explicit_target(modes) only runs for the
"applied-but-mismatch" case; change set_display_modes() so that both failure
cases (initial do_set_modes returned false) and the "applied but
all_modes_match() is false" path flow into the same fallback chain: attempt
do_set_modes_with_explicit_target(modes), then re-query via
get_current_display_modes(device_ids) and check all_modes_match(current_modes)
before returning; ensure you do not early-return on the first failure, propagate
and log Windows error codes consistently, and keep resource cleanup/error
handling identical to the existing mismatch path (use same logging and return
semantics only after fallback finishes).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 02d4a3b8-cb7e-49ae-a4a5-1e4cbe223299

📥 Commits

Reviewing files that changed from the base of the PR and between 2d4dd93 and 393174c.

📒 Files selected for processing (1)
  • src/platform/windows/display_device/device_modes.cpp
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Windows
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/platform/windows/display_device/device_modes.cpp
src/platform/**

⚙️ CodeRabbit configuration file

src/platform/**: 平台抽象层代码(Windows/Linux/macOS)。确保各平台实现一致, 注意 Windows API 调用的错误处理和资源释放。

Files:

  • src/platform/windows/display_device/device_modes.cpp
🔇 Additional comments (1)
src/platform/windows/display_device/device_modes.cpp (1)

233-275: 这里的 targetModeInfoIdx 读取在本代码库中是正确的,无需额外的 DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE 门控。

根据 windows_utils.cpp 的代码文档(第 494-499、516-521 行等),微软文档虽然声称该字段仅在设置 DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE 标志时有效,但这个结论经验证是"BS"(文档的复制粘贴错误)。实际的联合体可访问性取决于查询时是否指定了 QDC_VIRTUAL_MODE_AWARE 标志,本函数已满足此要求(query_display_config() 使用该标志)。

代码已通过以下方式防御不可用的索引:

  • target_idx != DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID 检查
  • target_idx < display_data->modes.size() 边界检查
  • infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET 类型验证

关于桌面图像同步的顾虑在本代码库中不适用,因为代码中无相关的 DISPLAYCONFIG_DESKTOP_IMAGE_INFO 处理。

Comment thread src/platform/windows/display_device/device_modes.cpp Outdated
The explicit target mode fallback was only reachable when the first
do_set_modes() call succeeded but mode validation failed. When the
first call itself fails with ERROR_GEN_FAILURE (the primary scenario
in #594), the old early return prevented any fallback from running.

Remove the early return, store the first attempt result, and flatten
all three attempts into a single unconditional fallback chain so that
do_set_modes_with_explicit_target() is tried regardless of whether the
previous calls failed or returned mismatched modes.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/windows/display_device/device_modes.cpp (1)

430-437: ⚠️ Potential issue | 🟠 Major

调整 rollback 前后的目标模式信息捕获范围,避免显式 target timing 的持久化数据不完整恢复。

do_set_modes_with_explicit_target() 详细修改 targetVideoSignalInfo 内多个字段(activeSize、totalSize、vSyncFreq、hSyncFreq、pixelRate、scanLineOrdering),并以 SDC_SAVE_TO_DATABASE 持久化到 Windows 注册表;但 Line 377 的回滚快照 original_modes 只是 device_display_mode_t 结构体,仅包含分辨率和刷新率两个参数。

do_set_modes_with_explicit_target() 在 Line 430 返回成功但 Line 432 验证失败,Line 437 的回滚 do_set_modes(original_modes, allow_changes) 会清空目标模式索引,由 Windows 基于分辨率和刷新率自动生成新的 targetVideoSignalInfo 并持久化,导致数据库内留存与原始状态不一致的配置。

建议在进入显式 target 回退路径前保存完整的 DISPLAYCONFIG_PATH_INFO[]DISPLAYCONFIG_MODE_INFO[] 快照,验证失败时按完整快照回滚,避免部分持久化数据的丢失。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/platform/windows/display_device/device_modes.cpp` around lines 430 - 437,
The rollback snapshot is incomplete: do_set_modes_with_explicit_target() mutates
multiple fields inside targetVideoSignalInfo and persists them
(SDC_SAVE_TO_DATABASE) but original_modes only holds resolution/refresh; capture
full DISPLAYCONFIG_PATH_INFO[] and DISPLAYCONFIG_MODE_INFO[] snapshots before
calling do_set_modes_with_explicit_target(modes) (use the same structures the
API writes to), then if get_current_display_modes(device_ids) indicates mismatch
after the explicit-target attempt, call a new restore routine that reapplies the
saved DISPLAYCONFIG_PATH_INFO/ DISPLAYCONFIG_MODE_INFO arrays (rather than
do_set_modes(original_modes,...)) to fully restore the persisted
targetVideoSignalInfo state and avoid partial/default regeneration by Windows.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/windows/display_device/device_modes.cpp`:
- Around line 233-283: You updated source mode, path->targetInfo.refreshRate and
targetVideoSignalInfo but did not clear the desktop-image index, so when using
SDC_VIRTUAL_MODE_AWARE a stale DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE entry
(with old size) can make SetDisplayConfig fail with ERROR_GEN_FAILURE; fix by
calling w_utils::set_desktop_index(*path, boost::none) after applying the
in-place target-mode updates (same place do_set_modes() used) so Windows will
reselect the desktop image entry before calling SetDisplayConfig with the
SDC_VIRTUAL_MODE_AWARE flags.

---

Outside diff comments:
In `@src/platform/windows/display_device/device_modes.cpp`:
- Around line 430-437: The rollback snapshot is incomplete:
do_set_modes_with_explicit_target() mutates multiple fields inside
targetVideoSignalInfo and persists them (SDC_SAVE_TO_DATABASE) but
original_modes only holds resolution/refresh; capture full
DISPLAYCONFIG_PATH_INFO[] and DISPLAYCONFIG_MODE_INFO[] snapshots before calling
do_set_modes_with_explicit_target(modes) (use the same structures the API writes
to), then if get_current_display_modes(device_ids) indicates mismatch after the
explicit-target attempt, call a new restore routine that reapplies the saved
DISPLAYCONFIG_PATH_INFO/ DISPLAYCONFIG_MODE_INFO arrays (rather than
do_set_modes(original_modes,...)) to fully restore the persisted
targetVideoSignalInfo state and avoid partial/default regeneration by Windows.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6916f8eb-1ab2-48b2-bc58-31b4e5713fe3

📥 Commits

Reviewing files that changed from the base of the PR and between 393174c and 0cd3f75.

📒 Files selected for processing (1)
  • src/platform/windows/display_device/device_modes.cpp
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/platform/windows/display_device/device_modes.cpp
src/platform/**

⚙️ CodeRabbit configuration file

src/platform/**: 平台抽象层代码(Windows/Linux/macOS)。确保各平台实现一致, 注意 Windows API 调用的错误处理和资源释放。

Files:

  • src/platform/windows/display_device/device_modes.cpp

Comment thread src/platform/windows/display_device/device_modes.cpp
A stale DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE entry (with the old
resolution dimensions) in the modes array can cause SetDisplayConfig to
return ERROR_GEN_FAILURE when SDC_VIRTUAL_MODE_AWARE is used, even when
the target mode entry itself is correctly updated in-place.

Call w_utils::set_desktop_index(*path, boost::none) after applying the
in-place target signal updates so Windows reselects an appropriate
desktop image entry, matching the pattern already used in do_set_modes().
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/platform/windows/display_device/device_modes.cpp`:
- Around line 233-281: The code sets changes_applied when updating source_mode
or path refresh rate but only calls w_utils::set_desktop_index(*path,
boost::none) when path->targetInfo.targetModeInfoIdx is valid and a
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET, leaving stale desktop-image entries when
targetModeInfoIdx is invalid; fix by either (A) if
path->targetInfo.targetModeInfoIdx == DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID
or out-of-range or not a TARGET, return false immediately (so SetDisplayConfig()
isn't called with stale desktop entries), or (B) always clear the desktop image
index whenever changes_applied is set (call w_utils::set_desktop_index(*path,
boost::none) whenever resolution_changed || refresh_rate_changed) before
proceeding to SetDisplayConfig(); reference path->targetInfo.targetModeInfoIdx,
DISPLAYCONFIG_PATH_TARGET_MODE_IDX_INVALID, DISPLAYCONFIG_MODE_INFO_TYPE_TARGET,
changes_applied, w_utils::set_desktop_index, and SetDisplayConfig in your
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5b563b86-d11e-4cff-88ca-a96ecdd30e97

📥 Commits

Reviewing files that changed from the base of the PR and between 0cd3f75 and 074de9e.

📒 Files selected for processing (1)
  • src/platform/windows/display_device/device_modes.cpp
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Windows
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/platform/windows/display_device/device_modes.cpp
src/platform/**

⚙️ CodeRabbit configuration file

src/platform/**: 平台抽象层代码(Windows/Linux/macOS)。确保各平台实现一致, 注意 Windows API 调用的错误处理和资源释放。

Files:

  • src/platform/windows/display_device/device_modes.cpp
🔇 Additional comments (1)
src/platform/windows/display_device/device_modes.cpp (1)

390-439: 这段回退链修正方向是对的。

现在“首轮 SetDisplayConfig() 直接失败”和“调用成功但校验不匹配”都会继续进入严格重试,再进入 explicit-target fallback,已经覆盖了 #594 的主故障路径。

Comment thread src/platform/windows/display_device/device_modes.cpp
Previously the function could proceed to SetDisplayConfig() with a stale
desktop image entry (from old resolution) when targetModeInfoIdx was
INVALID or the mode entry was not of TARGET type. This would cause
ERROR_GEN_FAILURE under SDC_VIRTUAL_MODE_AWARE.

Change the nested if-guards into early returns so the function bails out
immediately if no valid TARGET-type entry exists, ensuring SetDisplayConfig
is only called when the full explicit target configuration is valid.
@qiin2333 qiin2333 merged commit e80013e into master Apr 16, 2026
4 checks passed
@qiin2333 qiin2333 deleted the fix/explicit-target-mode-fallback branch April 16, 2026 13:48
@qiin2333 qiin2333 restored the fix/explicit-target-mode-fallback branch April 16, 2026 13:51
@qiin2333 qiin2333 deleted the fix/explicit-target-mode-fallback branch April 16, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: 2560x1600x144 分辨率设置失败 (ERROR_GEN_FAILURE) - Windows CCD 拓扑数据库兼容问题

1 participant