Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/compile_definitions/windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ set(PLATFORM_TARGET_FILES
"${CMAKE_SOURCE_DIR}/src/platform/windows/display_ram.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/display_wgc.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/display_amd.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/display_vdd.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/audio.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/mic_write.cpp"
"${CMAKE_SOURCE_DIR}/src/platform/windows/display_device/device_hdr_states.cpp"
Expand Down
96 changes: 96 additions & 0 deletions src/platform/windows/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,4 +546,100 @@ namespace platf::dxgi {
release_snapshot() override;
};

/**
* VDD direct-capture: opens the named D3D11 shared texture exported by
* the ZakoVDD driver (SharedFrameExporter). This bypasses DXGI Desktop
* Duplication / WGC and works in SYSTEM service context, before user logon,
* across session switch, and with full HDR — at the cost of only being able
* to capture VDD virtual monitors (not physical displays).
*/
class vdd_capture_t {
public:
vdd_capture_t();
~vdd_capture_t();

/**
* @brief Open the named shared texture / event / metadata for the given
* VDD monitor index. Must be called from the same D3D11 device
* that will be used for downstream encoding.
* @param d3d_device D3D11 device on the same adapter LUID as VDD's RenderAdapter.
* @param monitor_idx VDD-internal monitor index (0..N-1).
*/
int
init(ID3D11Device *d3d_device, unsigned int monitor_idx);

/**
* @brief Wait for the next frame (event-driven, no polling).
* @param timeout Maximum time to wait.
* @param out Receives a Texture2D reference holding the new frame.
* The caller MUST call release_frame() before next_frame()
* to release the keyed mutex.
* @param out_frame_qpc QPC value at producer-side push (for latency tracing).
*/
capture_e
next_frame(std::chrono::milliseconds timeout, ID3D11Texture2D **out, uint64_t &out_frame_qpc);

/**
* @brief Release the current keyed-mutex hold so the producer can write again.
*/
capture_e
release_frame();

/**
* @brief Reported producer-side dimensions / format / HDR metadata.
*/
UINT width() const { return m_width; }
UINT height() const { return m_height; }
DXGI_FORMAT format() const { return m_format; }
bool is_hdr() const { return m_is_hdr; }
float max_nits() const { return m_max_nits; }
float min_nits() const { return m_min_nits; }
float max_fall() const { return m_max_fall; }

private:
void close();

HANDLE m_hMeta = nullptr;
void *m_pMeta = nullptr;
HANDLE m_hEvent = nullptr;
texture2d_t m_sharedTex;
keyed_mutex_t m_keyedMutex;
bool m_holdsKey = false;

UINT m_width = 0;
UINT m_height = 0;
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
bool m_is_hdr = false;
float m_max_nits = 0.0f;
float m_min_nits = 0.0f;
float m_max_fall = 0.0f;
UINT64 m_lastFrameCounter = 0;
};

/**
* Display backend that consumes frames from the ZakoVDD virtual display
* driver via vdd_capture_t. Mirrors display_amd_vram_t / display_wgc_vram_t.
*/
class display_vdd_vram_t: public display_vram_t {
vdd_capture_t dup;
unsigned int monitor_idx = 0;
ID3D11Texture2D *current_frame = nullptr; // Borrowed ref from dup.next_frame, released in release_snapshot

public:
int
init(const ::video::config_t &config, const std::string &display_name);
capture_e
snapshot(const pull_free_image_cb_t &pull_free_image_cb, std::shared_ptr<platf::img_t> &img_out, std::chrono::milliseconds timeout, bool cursor_visible) override;
capture_e
release_snapshot() override;

// Override HDR queries to use producer-reported metadata from
// SharedFrameMetadata, instead of querying DXGI on the virtual output
// (which may not propagate the producer's static HDR meta correctly).
bool
is_hdr() override;
bool
get_hdr_metadata(SS_HDR_METADATA &metadata) override;
};
Comment on lines +591 to +643
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

把 VDD 的 HDR 元数据接到 display 接口上。

这里暴露了 vdd_capture_t 的 HDR 字段,但 display_vdd_vram_t 没有覆盖 is_hdr() / get_hdr_metadata();当前会继续走 display_base_t 的 DXGI output 查询,导致 producer 共享内存里的 HDR 元数据被忽略。

建议在 display_vdd_vram_t 上覆盖这两个方法,并用 dup.is_hdr() / dup.max_nits() / dup.min_nits() / dup.max_fall() 填充 SS_HDR_METADATA

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

In `@src/platform/windows/display.h` around lines 591 - 635, Implement HDR
passthrough on display_vdd_vram_t by overriding is_hdr() and get_hdr_metadata()
to return the VDD capture's metadata instead of querying DXGI; inside
display_vdd_vram_t add overrides for bool is_hdr() const and void
get_hdr_metadata(SS_HDR_METADATA &out) const (or the project-equivalent getter)
that query dup.is_hdr(), dup.max_nits(), dup.min_nits(), and dup.max_fall() and
populate the SS_HDR_METADATA struct accordingly, ensuring these methods are
marked override so the producer shared-memory HDR metadata is used.


} // namespace platf::dxgi
6 changes: 6 additions & 0 deletions src/platform/windows/display_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,12 @@ namespace platf {
if (type == "amd" && hwdevice_type == mem_type_e::dxgi) {
ret = try_init(std::make_shared<dxgi::display_amd_vram_t>());
}
else if (type == "vdd" && hwdevice_type == mem_type_e::dxgi) {
// ZakoVDD direct shared-texture capture. Works in SYSTEM context and
// before user logon. Only valid when the selected display is a VDD
// virtual monitor.
ret = try_init(std::make_shared<dxgi::display_vdd_vram_t>());
}
else if (type == "ddx") {
if (hwdevice_type == mem_type_e::dxgi) {
ret = try_init(std::make_shared<dxgi::display_ddup_vram_t>());
Expand Down
Loading
Loading