Skip to content

Commit 5d70b2b

Browse files
committed
Performance improvements ⭐
1 parent aa359a8 commit 5d70b2b

8 files changed

Lines changed: 44 additions & 39 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "windows-capture"
3-
version = "2.0.0-alpha.1"
3+
version = "2.0.0-alpha.2"
44
authors = ["NiiightmareXD"]
55
edition = "2024"
66
description = "Fastest Windows Screen Capture Library For Rust 🔥"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Add this dependency to your `Cargo.toml`:
3939

4040
```toml
4141
[dependencies]
42-
windows-capture = "2.0.0-alpha.1"
42+
windows-capture = "2.0.0-alpha.2"
4343
```
4444

4545
Or run this command:

src/dxgi_duplication_api.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub enum Error {
6969
/// Unsupported color format encountered.
7070
#[error("Unsupported color format: {0:?}")]
7171
UnsupportedColorFormat(DXGI_FORMAT),
72-
/// Invalid or mismatched staging texture supplied to [`DuplicationFrame::buffer_with`].
72+
/// Invalid or mismatched staging texture supplied to [`DxgiDuplicationFrame::buffer_with`].
7373
#[error("Invalid staging texture: {0}")]
7474
InvalidStagingTexture(&'static str),
7575
/// Image encoding failed.
@@ -107,7 +107,6 @@ impl DxgiDuplicationApi {
107107
///
108108
/// Internally creates a Direct3D 11 device and immediate context using the crate's d3d11
109109
/// module.
110-
#[inline]
111110
pub fn new(monitor: Monitor) -> Result<Self, Error> {
112111
// Create D3D11 device and context.
113112
let (d3d_device, d3d_device_context) = create_d3d_device()?;
@@ -178,20 +177,25 @@ impl DxgiDuplicationApi {
178177
/// Acquires the next frame and updates the internal texture.
179178
///
180179
/// This call will block up to `timeout_ms` milliseconds. If no new frame arrives within
181-
/// the timeout, [`Error::FrameTimeout`] is returned. If duplication access is lost,
180+
/// the timeout, [`Error::Timeout`] is returned. If duplication access is lost,
182181
/// [`Error::AccessLost`] is returned and a new duplication should be created via
183182
/// [`DxgiDuplicationApi::new`].
184183
///
185-
/// The returned [`DuplicationFrame`] allows you to map the current full desktop image via
186-
/// [`DuplicationFrame::buffer`]. It contains the list of dirty rectangles reported for this
184+
/// Main reasons for [`Error::AccessLost`] include:
185+
/// - The display mode of the output changed (e.g. resolution or color format change).
186+
/// - The user switched to a different desktop (e.g. via Ctrl+Alt+Del or Fast User Switching).
187+
/// - Switch from DWM on, DWM off, or other full-screen application
188+
///
189+
/// The returned [`DxgiDuplicationFrame`] allows you to map the current full desktop image via
190+
/// [`DxgiDuplicationFrame::buffer`]. It contains the list of dirty rectangles reported for this
187191
/// frame.
188192
///
189193
/// # Errors
190-
/// - [`Error::FrameTimeout`] when no frame arrives within `timeout_ms`
194+
/// - [`Error::Timeout`] when no frame arrives within `timeout_ms`
191195
/// - [`Error::AccessLost`] when duplication access is lost and must be recreated
192196
/// - [`Error::WindowsError`] for other Windows API failures during frame acquisition
193197
#[inline]
194-
pub fn acquire_next_frame(&mut self, timeout_ms: u32) -> Result<DuplicationFrame<'_>, Error> {
198+
pub fn acquire_next_frame(&mut self, timeout_ms: u32) -> Result<DxgiDuplicationFrame<'_>, Error> {
195199
let mut frame_info = DXGI_OUTDUPL_FRAME_INFO::default();
196200
let mut resource = None;
197201

@@ -219,7 +223,7 @@ impl DxgiDuplicationApi {
219223
let mut frame_desc = D3D11_TEXTURE2D_DESC::default();
220224
unsafe { frame_texture.GetDesc(&mut frame_desc) };
221225

222-
Ok(DuplicationFrame {
226+
Ok(DxgiDuplicationFrame {
223227
d3d_device: &self.d3d_device,
224228
d3d_device_context: &self.d3d_device_context,
225229
duplication: &self.duplication,
@@ -232,8 +236,8 @@ impl DxgiDuplicationApi {
232236

233237
/// Represents a pre-assembled full desktop image for the current frame,
234238
/// backed by the internal GPU texture.
235-
/// Call [`DuplicationFrame::buffer`] to obtain a CPU-readable [`crate::frame::FrameBuffer`].
236-
pub struct DuplicationFrame<'a> {
239+
/// Call [`DxgiDuplicationFrame::buffer`] to obtain a CPU-readable [`crate::frame::FrameBuffer`].
240+
pub struct DxgiDuplicationFrame<'a> {
237241
d3d_device: &'a ID3D11Device,
238242
d3d_device_context: &'a ID3D11DeviceContext,
239243
duplication: &'a IDXGIOutputDuplication,
@@ -242,7 +246,7 @@ pub struct DuplicationFrame<'a> {
242246
frame_info: DXGI_OUTDUPL_FRAME_INFO,
243247
}
244248

245-
impl<'a> DuplicationFrame<'a> {
249+
impl<'a> DxgiDuplicationFrame<'a> {
246250
/// Gets the width of the frame.
247251
#[inline]
248252
#[must_use]
@@ -308,7 +312,7 @@ impl<'a> DuplicationFrame<'a> {
308312
/// you can use [`crate::frame::FrameBuffer::as_nopadding_buffer`] to obtain a packed
309313
/// representation.
310314
#[inline]
311-
pub fn buffer<'b>(&'b mut self) -> Result<DuplicationFrameBuffer<'b>, Error> {
315+
pub fn buffer<'b>(&'b mut self) -> Result<DxgiDuplicationFrameBuffer<'b>, Error> {
312316
// Staging texture settings
313317
let texture_desc = D3D11_TEXTURE2D_DESC {
314318
Width: self.texture_desc.Width,
@@ -353,7 +357,7 @@ impl<'a> DuplicationFrame<'a> {
353357
_ => return Err(Error::UnsupportedColorFormat(self.texture_desc.Format)),
354358
};
355359

356-
Ok(DuplicationFrameBuffer::new(
360+
Ok(DxgiDuplicationFrameBuffer::new(
357361
mapped_frame_data,
358362
self.texture_desc.Width,
359363
self.texture_desc.Height,
@@ -371,7 +375,7 @@ impl<'a> DuplicationFrame<'a> {
371375
start_y: u32,
372376
end_x: u32,
373377
end_y: u32,
374-
) -> Result<DuplicationFrameBuffer<'b>, Error> {
378+
) -> Result<DxgiDuplicationFrameBuffer<'b>, Error> {
375379
if start_x >= end_x || start_y >= end_y {
376380
return Err(Error::InvalidSize);
377381
}
@@ -425,7 +429,7 @@ impl<'a> DuplicationFrame<'a> {
425429
_ => return Err(Error::UnsupportedColorFormat(self.texture_desc.Format)),
426430
};
427431

428-
Ok(DuplicationFrameBuffer::new(
432+
Ok(DxgiDuplicationFrameBuffer::new(
429433
mapped_frame_data,
430434
texture_width,
431435
texture_height,
@@ -441,15 +445,16 @@ impl<'a> DuplicationFrame<'a> {
441445
/// The `staging` texture must be a `D3D11_USAGE_STAGING` 2D texture with CPU read/write access,
442446
/// matching the frame’s width/height/format.
443447
#[inline]
444-
pub fn buffer_with<'s>(&'s mut self, staging: &'s mut StagingTexture) -> Result<DuplicationFrameBuffer<'s>, Error> {
448+
pub fn buffer_with<'s>(
449+
&'s mut self,
450+
staging: &'s mut StagingTexture,
451+
) -> Result<DxgiDuplicationFrameBuffer<'s>, Error> {
445452
// Validate geometry/format match.
446-
let sdesc = staging.desc();
447-
448-
if sdesc.Width != self.texture_desc.Width || sdesc.Height != self.texture_desc.Height {
453+
let desc = staging.desc();
454+
if desc.Width != self.texture_desc.Width || desc.Height != self.texture_desc.Height {
449455
return Err(Error::InvalidStagingTexture("geometry must match the frame"));
450456
}
451-
452-
if sdesc.Format != self.texture_desc.Format {
457+
if desc.Format != self.texture_desc.Format {
453458
return Err(Error::InvalidStagingTexture("format must match the frame"));
454459
}
455460

@@ -476,7 +481,7 @@ impl<'a> DuplicationFrame<'a> {
476481
_ => return Err(Error::UnsupportedColorFormat(self.texture_desc.Format)),
477482
};
478483

479-
Ok(DuplicationFrameBuffer::new(
484+
Ok(DxgiDuplicationFrameBuffer::new(
480485
mapped_frame_data,
481486
self.texture_desc.Width,
482487
self.texture_desc.Height,
@@ -498,7 +503,8 @@ impl<'a> DuplicationFrame<'a> {
498503
start_y: u32,
499504
end_x: u32,
500505
end_y: u32,
501-
) -> Result<DuplicationFrameBuffer<'s>, Error> {
506+
) -> Result<DxgiDuplicationFrameBuffer<'s>, Error> {
507+
// Validate crop rectangle
502508
if start_x >= end_x || start_y >= end_y {
503509
return Err(Error::InvalidSize);
504510
}
@@ -507,11 +513,11 @@ impl<'a> DuplicationFrame<'a> {
507513
let crop_height = end_y - start_y;
508514

509515
// Validate format and capacity
510-
let sdesc = staging.desc();
511-
if sdesc.Format != self.texture_desc.Format {
516+
let desc = staging.desc();
517+
if desc.Format != self.texture_desc.Format {
512518
return Err(Error::InvalidStagingTexture("format must match the frame"));
513519
}
514-
if sdesc.Width < crop_width || sdesc.Height < crop_height {
520+
if desc.Width < crop_width || desc.Height < crop_height {
515521
return Err(Error::InvalidStagingTexture("staging texture too small for crop region"));
516522
}
517523

@@ -549,7 +555,7 @@ impl<'a> DuplicationFrame<'a> {
549555
_ => return Err(Error::UnsupportedColorFormat(self.texture_desc.Format)),
550556
};
551557

552-
Ok(DuplicationFrameBuffer::new(
558+
Ok(DxgiDuplicationFrameBuffer::new(
553559
mapped_frame_data,
554560
crop_width,
555561
crop_height,
@@ -579,7 +585,7 @@ impl<'a> DuplicationFrame<'a> {
579585
}
580586
}
581587

582-
impl Drop for DuplicationFrame<'_> {
588+
impl Drop for DxgiDuplicationFrame<'_> {
583589
fn drop(&mut self) {
584590
// Release the frame back to the duplication interface.
585591
unsafe {
@@ -596,7 +602,7 @@ impl Drop for DuplicationFrame<'_> {
596602
/// let mut buffer = frame.buffer()?;
597603
/// buffer.save_as_image("screenshot.png", ImageFormat::Png)?;
598604
/// ```
599-
pub struct DuplicationFrameBuffer<'a> {
605+
pub struct DxgiDuplicationFrameBuffer<'a> {
600606
raw_buffer: &'a mut [u8],
601607
width: u32,
602608
height: u32,
@@ -605,7 +611,7 @@ pub struct DuplicationFrameBuffer<'a> {
605611
color_format: ColorFormat,
606612
}
607613

608-
impl<'a> DuplicationFrameBuffer<'a> {
614+
impl<'a> DxgiDuplicationFrameBuffer<'a> {
609615
/// Constructs a new `FrameBuffer`.
610616
#[inline]
611617
#[must_use]

src/encoder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ pub enum ImageFormat {
8787
///
8888
/// # Example
8989
/// ```no_run
90-
/// use windows_capture::encoder::ImageEncoder;
91-
/// use windows_capture::encoder::ImageFormat;
90+
/// use windows_capture::encoder::{ImageEncoder, ImageFormat};
9291
/// use windows_capture::settings::ColorFormat;
9392
///
9493
/// let width = 320u32;

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
//!
2525
//! ```toml
2626
//! [dependencies]
27-
//! windows-capture = "2.0.0-alpha.1"
27+
//! windows-capture = "2.0.0-alpha.2"
2828
//! ```
2929
//! Or run this command:
3030
//!

windows-capture-python/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "windows-capture-python"
3-
version = "2.0.0-alpha.1"
3+
version = "2.0.0-alpha.2"
44
authors = ["NiiightmareXD"]
55
edition = "2021"
66
description = "Fastest Windows Screen Capture Library For Python 🔥"

windows-capture-python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "maturin"
44

55
[project]
66
name = "windows-capture"
7-
version = "2.0.0-alpha.1"
7+
version = "2.0.0-alpha.2"
88
description = "Fastest Windows Screen Capture Library For Python 🔥"
99
readme = "README-Python.md"
1010
requires-python = ">=3.9"

0 commit comments

Comments
 (0)