#![cfg_attr(not(feature = "9ex"), allow(unused_imports))]
use crate::*;
use crate::d3d9::*;
use winapi::shared::d3d9::{IDirect3DDevice9Ex, IDirect3DDevice9};
use winapi::shared::d3d9types::*;
use winapi::um::unknwnbase::IUnknown;
use winapi::um::wingdi::*;
use std::convert::TryInto;
use std::ptr::*;
#[cfg(feature = "9ex")]
#[derive(Clone)] #[repr(transparent)]
pub struct DeviceEx(pub(crate) mcom::Rc<IDirect3DDevice9Ex>);
#[cfg(feature = "9ex")] unsafe impl AsSafe<IUnknown > for DeviceEx { fn as_safe(&self) -> &IUnknown { &***self.0 } }
#[cfg(feature = "9ex")] unsafe impl AsSafe<IDirect3DDevice9 > for DeviceEx { fn as_safe(&self) -> &IDirect3DDevice9 { &**self.0 } }
#[cfg(feature = "9ex")] unsafe impl AsSafe<IDirect3DDevice9Ex > for DeviceEx { fn as_safe(&self) -> &IDirect3DDevice9Ex { &*self.0 } }
#[cfg(feature = "9ex")]
pub trait IDirect3DDevice9ExExt : AsSafe<IDirect3DDevice9Ex> {
fn check_device_state(&self, destination_window: impl AsHWND) -> ErrorKind {
ErrorKind(unsafe { self.as_winapi().CheckDeviceState(destination_window.as_hwnd()) })
}
#[doc(hidden)]
fn _xxx_check_resource_residency(&self, resources: &mut [Resource]) -> ErrorKind {
let len : u16 = match resources.len().try_into() {
Ok(len) => len,
Err(_) => return THINERR::SLICE_OVERFLOW,
};
let len = u32::from(len);
let resources = resources.as_mut_ptr().cast(); ErrorKind(unsafe { self.as_winapi().CheckResourceResidency(resources, len) })
}
fn compose_rects(&self, src: &Surface, dst: &Surface, src_rect_descs: &VertexBuffer, num_rects: u32, dst_rect_descs: &VertexBuffer, operation: impl Into<ComposeRectsOp>, xoffset: i32, yoffset: i32) -> Result<(), MethodError> {
let (src, dst, src_rect_descs, dst_rect_descs) = (src.as_raw(), dst.as_raw(), src_rect_descs.as_raw(), dst_rect_descs.as_raw());
let operation = operation.into().into();
let hr = unsafe { self.as_winapi().ComposeRects(src, dst, src_rect_descs, num_rects, dst_rect_descs, operation, xoffset, yoffset) };
MethodError::check("IDirect3DDevice9Ex::ComposeRects", hr)
}
fn create_depth_stencil_surface_ex(&self, width: u32, height: u32, format: impl Into<Format>, multi_sample: impl Into<MultiSampleType>, multi_sample_quality: u32, discard: bool, _shared_handle: impl SharedHandleParam, usage: impl Into<Usage>) -> Result<Surface, MethodError> {
let format = format.into().into();
let multi_sample = multi_sample.into().into();
let discard = discard.into();
let shared_handle = null_mut();
let usage = usage.into().into();
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateDepthStencilSurfaceEx(width, height, format, multi_sample, multi_sample_quality, discard, &mut surface, shared_handle, usage) };
MethodError::check("IDirect3DDevice9Ex::CreateDepthStencilSurfaceEx", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn create_offscreen_plain_surface_ex(&self, width: u32, height: u32, format: impl Into<Format>, pool: impl Into<Pool>, _shared_handle: impl SharedHandleParam, usage: impl Into<Usage>) -> Result<Surface, MethodError> {
let format = format.into().into();
let pool = pool.into().into();
let shared_handle = null_mut();
let usage = usage.into().into();
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateOffscreenPlainSurfaceEx(width, height, format, pool, &mut surface, shared_handle, usage) };
MethodError::check("IDirect3DDevice9Ex::CreateOffscreenPlainSurfaceEx", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn create_render_target_ex(&self, width: u32, height: u32, format: impl Into<Format>, multi_sample: impl Into<MultiSampleType>, multi_sample_quality: u32, lockable: bool, _shared_handle: impl SharedHandleParam, usage: impl Into<Usage>) -> Result<Surface, MethodError> {
let format = format.into().into();
let multi_sample = multi_sample.into().into();
let lockable = lockable.into();
let shared_handle = null_mut();
let usage = usage.into().into();
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateRenderTargetEx(width, height, format, multi_sample, multi_sample_quality, lockable, &mut surface, shared_handle, usage) };
MethodError::check("IDirect3DDevice9Ex::CreateRenderTargetEx", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn get_display_mode_ex(&self, swap_chain: u32) -> Result<(D3DDISPLAYMODEEX, DisplayRotation), MethodError> {
let mut display_mode_ex = unsafe { std::mem::zeroed::<D3DDISPLAYMODEEX>() };
let mut rotation = 0;
let hr = unsafe { self.as_winapi().GetDisplayModeEx(swap_chain, &mut display_mode_ex, &mut rotation) };
MethodError::check("IDirect3DDevice9Ex::GetDisplayModeEx", hr)?;
Ok((display_mode_ex, DisplayRotation::from_unchecked(rotation)))
}
fn get_gpu_thread_priority(&self) -> Result<i32, MethodError> {
let mut pri = 0;
let hr = unsafe { self.as_winapi().GetGPUThreadPriority(&mut pri) };
MethodError::check("IDirect3DDevice9Ex::GetGPUThreadPriority", hr)?;
Ok(pri)
}
fn get_maximum_frame_latency(&self) -> Result<u32, MethodError> {
let mut max_latency = 0;
let hr = unsafe { self.as_winapi().GetMaximumFrameLatency(&mut max_latency) };
MethodError::check("IDirect3DDevice9Ex::GetMaximumFrameLatency", hr)?;
Ok(max_latency)
}
fn present_ex<'r>(&self, source_rect: impl IntoRectOrFull, dest_rect: impl IntoRectOrFull, dest_window_override: impl AsHWND, dirty_region: impl Into<Option<&'r RgnData>>, flags: impl Into<Present>) -> Result<(), MethodError> {
let source_rect = source_rect.into_rect();
let dest_rect = dest_rect.into_rect();
let source_rect = source_rect.as_ref().map_or(null(), |r| &**r);
let dest_rect = dest_rect.as_ref().map_or(null(), |r| &**r);
let dirty_region= dirty_region.into();
let flags = flags.into().into();
let dirty_region = match dirty_region {
None => null::<RGNDATA>(),
Some(dr) => {
if dr.rdh.dwSize as usize != std::mem::size_of::<RGNDATAHEADER>() { return Err(MethodError("Device::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.iType != RDH_RECTANGLES { return Err(MethodError("Device::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.nCount as usize > dr.buffer.len() { return Err(MethodError("Device::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.nRgnSize as usize > std::mem::size_of_val(dr) { return Err(MethodError("Device::present", THINERR::INVALID_STRUCT_FIELD)); }
let dr : *const RgnData = dr;
dr.cast()
},
};
let hr = unsafe { self.as_winapi().PresentEx(source_rect.cast(), dest_rect.cast(), dest_window_override.as_hwnd(), dirty_region, flags) };
MethodError::check("IDirect3DDevice9Ex::PresentEx", hr)
}
fn reset_ex<'mode>(&self, presentation_parameters: &mut D3DPRESENT_PARAMETERS, fullscreen_display_mode: impl Into<Option<&'mode mut D3DDISPLAYMODEEX>>) -> Result<(), MethodError> {
let fullscreen_display_mode = fullscreen_display_mode.into().map_or(null_mut(), |dm| dm);
let hr = unsafe { self.as_winapi().ResetEx(presentation_parameters, fullscreen_display_mode) };
MethodError::check("IDirect3DDevice9Ex::ResetEx", hr)
}
fn set_convolution_mono_kernel_unweighted(&self, width: u32, height: u32) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetConvolutionMonoKernel(width, height, null_mut(), null_mut()) };
MethodError::check("IDirect3DDevice9Ex::SetConvolutionMonoKernel", hr)
}
fn set_convolution_mono_kernel(&self, rows: &mut [f32], cols: &mut [f32]) -> Result<(), MethodError> {
let width : u32 = rows.len().try_into().map_err(|_| MethodError("DeviceEx::set_convolution_mono_kernel", THINERR::SLICE_OVERFLOW))?;
let height : u32 = cols.len().try_into().map_err(|_| MethodError("DeviceEx::set_convolution_mono_kernel", THINERR::SLICE_OVERFLOW))?;
let hr = unsafe { self.as_winapi().SetConvolutionMonoKernel(width, height, rows.as_mut_ptr(), cols.as_mut_ptr()) };
MethodError::check("IDirect3DDevice9Ex::SetConvolutionMonoKernel", hr)
}
fn set_gpu_thread_priority(&self, priority: i32) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetGPUThreadPriority(priority) };
MethodError::check("IDirect3DDevice9Ex::SetGPUThreadPriority", hr)
}
fn set_maximum_frame_latency(&self, max_latency: u32) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetMaximumFrameLatency(max_latency) };
MethodError::check("IDirect3DDevice9Ex::SetMaximumFrameLatency", hr)
}
#[deprecated = "docs claim test_cooperative_level is no longer available for use - instead, use check_device_state"]
fn test_cooperative_level(&self) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().TestCooperativeLevel() };
MethodError::check("IDirect3DDevice9Ex::TestCooperativeLevel", hr)
}
fn wait_for_vblank(&self, swap_chain: u32) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().WaitForVBlank(swap_chain) };
MethodError::check("IDirect3DDevice9Ex::WaitForVBlank", hr)
}
}
#[cfg(feature = "9ex")]
impl<T: AsSafe<IDirect3DDevice9Ex>> IDirect3DDevice9ExExt for T {}