Skip to content

Commit

Permalink
zero copy and get direct3d device and context
Browse files Browse the repository at this point in the history
  • Loading branch information
mycrl committed Oct 19, 2024
1 parent 24fae7d commit 09d4f4a
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 45 deletions.
4 changes: 2 additions & 2 deletions examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
};

use windows_capture::{
capture::GraphicsCaptureApiHandler,
capture::{GraphicsCaptureApiHandler, RawDirect3DDevice},
encoder::{AudioSettingsBuilder, ContainerSettingsBuilder, VideoEncoder, VideoSettingsBuilder},
frame::Frame,
graphics_capture_api::InternalCaptureControl,
Expand All @@ -28,7 +28,7 @@ impl GraphicsCaptureApiHandler for Capture {
type Error = Box<dyn std::error::Error + Send + Sync>;

// Function that will be called to create the struct. The flags can be passed from settings.
fn new(message: Self::Flags) -> Result<Self, Self::Error> {
fn new(_: RawDirect3DDevice, message: Self::Flags) -> Result<Self, Self::Error> {
println!("Got The Flag: {message}");

let encoder = VideoEncoder::new(
Expand Down
25 changes: 6 additions & 19 deletions examples/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ use std::{
use clap::Parser;

use windows_capture::{
capture::GraphicsCaptureApiHandler,
encoder::{
AudioSettingsBuilder, ContainerSettingsBuilder, VideoEncoder, VideoSettingsBuilder,
},
capture::{GraphicsCaptureApiHandler, RawDirect3DDevice},
encoder::{AudioSettingsBuilder, ContainerSettingsBuilder, VideoEncoder, VideoSettingsBuilder},
frame::Frame,
graphics_capture_api::InternalCaptureControl,
monitor::Monitor,
Expand Down Expand Up @@ -55,7 +53,7 @@ impl GraphicsCaptureApiHandler for Capture {
type Error = Box<dyn std::error::Error + Send + Sync>;

// Function that will be called to create the struct. The flags can be passed from settings.
fn new(settings: Self::Flags) -> Result<Self, Self::Error> {
fn new(_: RawDirect3DDevice, settings: Self::Flags) -> Result<Self, Self::Error> {
println!("Capture started.");

let video_settings = VideoSettingsBuilder::new(settings.width, settings.height)
Expand Down Expand Up @@ -226,8 +224,7 @@ fn main() {

if let Some(window_name) = cli.window_name {
// May use Window::foreground() instead
let capture_item =
Window::from_contains_name(&window_name).expect("Window not found!");
let capture_item = Window::from_contains_name(&window_name).expect("Window not found!");

// Automatically detect window's width and height
let rect = capture_item.rect().expect("Failed to get window rect");
Expand All @@ -249,12 +246,7 @@ fn main() {
);
println!("Window size: {}x{}", width, height);

start_capture(
capture_item,
cursor_capture,
draw_border,
capture_settings,
);
start_capture(capture_item, cursor_capture, draw_border, capture_settings);
} else if let Some(index) = cli.monitor_index {
// May use Monitor::primary() instead
let capture_item =
Expand All @@ -276,12 +268,7 @@ fn main() {
println!("Monitor index: {}", index);
println!("Monitor size: {}x{}", width, height);

start_capture(
capture_item,
cursor_capture,
draw_border,
capture_settings,
);
start_capture(capture_item, cursor_capture, draw_border, capture_settings);
} else {
eprintln!("Either --window-name or --monitor-index must be provided");
std::process::exit(1);
Expand Down
40 changes: 37 additions & 3 deletions src/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use windows::{
Graphics::Capture::GraphicsCaptureItem,
Win32::{
Foundation::{HANDLE, LPARAM, WPARAM},
Graphics::Direct3D11::{ID3D11Device, ID3D11DeviceContext},
System::{
Threading::{GetCurrentThreadId, GetThreadId},
WinRT::{
Expand All @@ -29,6 +30,7 @@ use windows::{
};

use crate::{
d3d11::{self, create_d3d_device},
frame::Frame,
graphics_capture_api::{self, GraphicsCaptureApi, InternalCaptureControl},
settings::Settings,
Expand Down Expand Up @@ -207,6 +209,8 @@ pub enum GraphicsCaptureApiError<E> {
FailedToSetDispatcherQueueCompletedHandler,
#[error("Failed to convert item to GraphicsCaptureItem")]
ItemConvertFailed,
#[error("DirectX error: {0}")]
DirectXError(#[from] d3d11::Error),
#[error("Graphics capture error: {0}")]
GraphicsCaptureApiError(graphics_capture_api::Error),
#[error("New handler error: {0}")]
Expand Down Expand Up @@ -261,10 +265,20 @@ pub trait GraphicsCaptureApiHandler: Sized {
// Get current thread ID
let thread_id = unsafe { GetCurrentThreadId() };

// Create direct3d device and context
let (d3d_device, d3d_device_context) = create_d3d_device()?;

// Start capture
let result = Arc::new(Mutex::new(None));
let callback = Arc::new(Mutex::new(
Self::new(settings.flags).map_err(GraphicsCaptureApiError::NewHandlerError)?,
Self::new(
RawDirect3DDevice {
device: d3d_device.clone(),
context: d3d_device_context.clone(),
},
settings.flags,
)
.map_err(GraphicsCaptureApiError::NewHandlerError)?,
));

let item = settings
Expand All @@ -273,6 +287,8 @@ pub trait GraphicsCaptureApiHandler: Sized {
.map_err(|_| GraphicsCaptureApiError::ItemConvertFailed)?;

let mut capture = GraphicsCaptureApi::new(
d3d_device,
d3d_device_context,
item,
callback,
settings.cursor_capture,
Expand Down Expand Up @@ -374,10 +390,20 @@ pub trait GraphicsCaptureApiHandler: Sized {
// Get current thread ID
let thread_id = unsafe { GetCurrentThreadId() };

// Create direct3d device and context
let (d3d_device, d3d_device_context) = create_d3d_device()?;

// Start capture
let result = Arc::new(Mutex::new(None));
let callback = Arc::new(Mutex::new(
Self::new(settings.flags).map_err(GraphicsCaptureApiError::NewHandlerError)?,
Self::new(
RawDirect3DDevice {
device: d3d_device.clone(),
context: d3d_device_context.clone(),
},
settings.flags,
)
.map_err(GraphicsCaptureApiError::NewHandlerError)?,
));

let item = settings
Expand All @@ -386,6 +412,8 @@ pub trait GraphicsCaptureApiHandler: Sized {
.map_err(|_| GraphicsCaptureApiError::ItemConvertFailed)?;

let mut capture = GraphicsCaptureApi::new(
d3d_device,
d3d_device_context,
item,
callback.clone(),
settings.cursor_capture,
Expand Down Expand Up @@ -485,7 +513,7 @@ pub trait GraphicsCaptureApiHandler: Sized {
/// # Returns
///
/// Returns `Ok(Self)` if the struct creation was successful, otherwise returns an error of type `Self::Error`.
fn new(flags: Self::Flags) -> Result<Self, Self::Error>;
fn new(device: RawDirect3DDevice, flags: Self::Flags) -> Result<Self, Self::Error>;

/// Called every time a new frame is available.
///
Expand Down Expand Up @@ -513,3 +541,9 @@ pub trait GraphicsCaptureApiHandler: Sized {
Ok(())
}
}

#[derive(Clone)]
pub struct RawDirect3DDevice {
pub device: ID3D11Device,
pub context: ID3D11DeviceContext,
}
8 changes: 6 additions & 2 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,9 @@ impl VideoEncoder {
};

self.frame_sender.send(Some((
VideoEncoderSource::DirectX(SendDirectX::new(unsafe { frame.as_raw_surface() })),
VideoEncoderSource::DirectX(SendDirectX::new(unsafe {
frame.as_raw_surface().clone()
})),
timespan,
)))?;

Expand Down Expand Up @@ -1051,7 +1053,9 @@ impl VideoEncoder {
};

self.frame_sender.send(Some((
VideoEncoderSource::DirectX(SendDirectX::new(unsafe { frame.as_raw_surface() })),
VideoEncoderSource::DirectX(SendDirectX::new(unsafe {
frame.as_raw_surface().clone()
})),
timespan,
)))?;

Expand Down
30 changes: 14 additions & 16 deletions src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ impl<'a> Frame<'a> {
/// This method is unsafe because it returns a raw pointer to the IDirect3DSurface.
#[must_use]
#[inline]
pub unsafe fn as_raw_surface(&self) -> IDirect3DSurface {
self.frame_surface.clone()
pub unsafe fn as_raw_surface(&self) -> &IDirect3DSurface {
&self.frame_surface
}

/// Get the raw texture of the frame.
Expand All @@ -178,7 +178,17 @@ impl<'a> Frame<'a> {
///
/// The ID3D11Texture2D representing the raw texture of the frame.
#[inline]
pub fn texture(&self) -> Result<ID3D11Texture2D, Error> {
pub unsafe fn as_raw_texture(&self) -> &ID3D11Texture2D {
&self.frame_texture
}

/// Get the frame buffer.
///
/// # Returns
///
/// The FrameBuffer containing the frame data.
#[inline]
pub fn buffer(&mut self) -> Result<FrameBuffer, Error> {
// Texture Settings
let texture_desc = D3D11_TEXTURE2D_DESC {
Width: self.width,
Expand All @@ -192,7 +202,7 @@ impl<'a> Frame<'a> {
},
Usage: D3D11_USAGE_STAGING,
BindFlags: 0,
CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32 | D3D11_CPU_ACCESS_WRITE.0 as u32,
CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32,
MiscFlags: 0,
};

Expand All @@ -210,18 +220,6 @@ impl<'a> Frame<'a> {
self.context.CopyResource(&texture, &self.frame_texture);
};

Ok(texture)
}

/// Get the frame buffer.
///
/// # Returns
///
/// The FrameBuffer containing the frame data.
#[inline]
pub fn buffer(&mut self) -> Result<FrameBuffer, Error> {
let texture = self.texture()?;

// Map the texture to enable CPU access
let mut mapped_resource = D3D11_MAPPED_SUBRESOURCE::default();
unsafe {
Expand Down
5 changes: 3 additions & 2 deletions src/graphics_capture_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use windows::{

use crate::{
capture::GraphicsCaptureApiHandler,
d3d11::{self, create_d3d_device, create_direct3d_device, SendDirectX},
d3d11::{self, create_direct3d_device, SendDirectX},
frame::Frame,
settings::{ColorFormat, CursorCaptureSettings, DrawBorderSettings},
};
Expand Down Expand Up @@ -117,6 +117,8 @@ impl GraphicsCaptureApi {
T: GraphicsCaptureApiHandler<Error = E> + Send + 'static,
E: Send + Sync + 'static,
>(
d3d_device: ID3D11Device,
d3d_device_context: ID3D11DeviceContext,
item: GraphicsCaptureItem,
callback: Arc<Mutex<T>>,
cursor_capture: CursorCaptureSettings,
Expand All @@ -141,7 +143,6 @@ impl GraphicsCaptureApi {
}

// Create DirectX devices
let (d3d_device, d3d_device_context) = create_d3d_device()?;
let direct3d_device = create_direct3d_device(&d3d_device)?;

let pixel_format = DirectXPixelFormat(color_format as i32);
Expand Down
6 changes: 5 additions & 1 deletion windows-capture-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::sync::Arc;
use ::windows_capture::{
capture::{
CaptureControl, CaptureControlError, GraphicsCaptureApiError, GraphicsCaptureApiHandler,
RawDirect3DDevice,
},
frame::{self, Frame},
graphics_capture_api::InternalCaptureControl,
Expand Down Expand Up @@ -368,7 +369,10 @@ impl GraphicsCaptureApiHandler for InnerNativeWindowsCapture {
type Error = InnerNativeWindowsCaptureError;

#[inline]
fn new((on_frame_arrived_callback, on_closed): Self::Flags) -> Result<Self, Self::Error> {
fn new(
_: RawDirect3DDevice,
(on_frame_arrived_callback, on_closed): Self::Flags,
) -> Result<Self, Self::Error> {
Ok(Self {
on_frame_arrived_callback,
on_closed,
Expand Down

0 comments on commit 09d4f4a

Please sign in to comment.