#![allow(dead_code)]
use crate::*;
use crate::d3d9::*;
use crate::d3d9_h::interfaces::device_draw::{IndexData, VertexStreamData};
use abibool::bool32;
use bytemuck::Zeroable;
use winapi::shared::d3d9::IDirect3DDevice9;
use winapi::shared::d3d9types::*;
use winapi::shared::windef::RECT;
use winapi::um::unknwnbase::IUnknown;
use winapi::um::wingdi::*;
use std::convert::TryInto;
use std::ptr::*;
pub(crate) const MAX_BUFFER_ALLOC : u32 = 0xFFFF_0000;
#[derive(Clone)] #[repr(transparent)]
pub struct Device(pub(crate) mcom::Rc<IDirect3DDevice9>);
unsafe impl AsSafe<IUnknown > for Device { fn as_safe(&self) -> &IUnknown { &**self.0 } }
unsafe impl AsSafe<IDirect3DDevice9 > for Device { fn as_safe(&self) -> &IDirect3DDevice9 { &*self.0 } }
pub trait IDirect3DDevice9Ext : AsSafe<IDirect3DDevice9> + Sized {
fn begin_scene(&self) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().BeginScene() };
MethodError::check("IDirect3DDevice9::BeginScene", hr)
}
fn begin_state_block(&self) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().BeginStateBlock() };
MethodError::check("IDirect3DDevice9::BeginStateBlock", hr)
}
fn clear(&self, rects: Option<&[Rect]>, color: Option<Color>, depth: Option<f32>, stencil: Option<u32>) -> Result<(), MethodError> {
let n : u32 = rects.map_or(0, |r| r.len()).try_into().map_err(|_| MethodError("Device::clear", D3DERR::INVALIDCALL))?;
let rects = rects.map_or(null(), |r| r.as_ptr().cast());
let flags =
((color .is_some() as u32) * D3DCLEAR_TARGET ) |
((depth .is_some() as u32) * D3DCLEAR_ZBUFFER) |
((stencil.is_some() as u32) * D3DCLEAR_STENCIL);
let color = color.unwrap_or_default().into();
let depth = depth.unwrap_or(0.0);
let stencil = stencil.unwrap_or(0);
let hr = unsafe { self.as_winapi().Clear(n, rects, flags, color, depth, stencil) };
MethodError::check("IDirect3DDevice9::Clear", hr)
}
fn color_fill(&self, surface: &Surface, rect: Option<Rect>, color: impl Into<Color>) -> Result<(), MethodError> {
let rect = rect.map(RECT::from);
let rect = rect.as_ref().map_or(null(), |r| r);
let hr = unsafe { self.as_winapi().ColorFill(surface.as_raw(), rect, color.into().into()) };
MethodError::check("IDirect3DDevice9::ColorFill", hr)
}
unsafe fn create_additional_swap_chain(&self, presentation_parameters: &mut D3DPRESENT_PARAMETERS) -> Result<SwapChain, MethodError> {
let mut swap_chain = null_mut();
let hr = self.as_winapi().CreateAdditionalSwapChain(presentation_parameters, &mut swap_chain);
MethodError::check("IDirect3DDevice9::CreateAdditionalSwapChain", hr)?;
Ok(SwapChain::from_raw(swap_chain))
}
fn create_cube_texture(&self, edge_length: u32, levels: u32, usage: impl Into<Usage>, format: impl Into<Format>, pool: impl Into<Pool>, _shared_handle: impl SharedHandleParam) -> Result<CubeTexture, MethodError> {
let mut texture = null_mut();
let hr = unsafe { self.as_winapi().CreateCubeTexture(edge_length, levels, usage.into().into(), format.into().into(), pool.into().into(), &mut texture, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateCubeTexture", hr)?;
Ok(unsafe { CubeTexture::from_raw(texture) })
}
fn create_depth_stencil_surface(&self, width: u32, height: u32, format: Format, multi_sample: MultiSample, multi_sample_quality: u32, discard: bool, _shared_handle: impl SharedHandleParam) -> Result<Surface, MethodError> {
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateDepthStencilSurface(width, height, format.into(), multi_sample.into(), multi_sample_quality, discard.into(), &mut surface, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateDepthStencilSurface", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn create_index_buffer(&self, length: u32, usage: impl Into<Usage>, format: impl Into<Format>, pool: impl Into<Pool>, shared_handle: impl SharedHandleParam) -> Result<IndexBuffer, MethodError> {
if length > MAX_BUFFER_ALLOC { return Err(MethodError("Device::create_index_buffer", THINERR::ALLOC_OVERFLOW)); }
let _ = shared_handle;
let mut buffer = null_mut();
let hr = unsafe { self.as_winapi().CreateIndexBuffer(length, usage.into().into(), format.into().into(), pool.into().into(), &mut buffer, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateIndexBuffer", hr)?;
Ok(unsafe { IndexBuffer::from_raw(buffer) })
}
fn create_offscreen_plain_surface(&self, width: u32, height: u32, format: Format, pool: Pool, _shared_handle: impl SharedHandleParam) -> Result<Surface, MethodError> {
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateOffscreenPlainSurface(width, height, format.into(), pool.into(), &mut surface, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateOffscreenPlainSurface", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
unsafe fn create_pixel_shader(&self, function: &[u32]) -> Result<PixelShader, MethodError> {
let mut shader = null_mut();
let hr = self.as_winapi().CreatePixelShader(function.as_ptr(), &mut shader);
MethodError::check("IDirect3DDevice9::CreatePixelShader", hr)?;
Ok(PixelShader::from_raw(shader))
}
fn create_query(&self, type_: QueryType) -> Result<Query, MethodError> {
let mut query = null_mut();
let hr = unsafe { self.as_winapi().CreateQuery(type_.into(), &mut query) };
MethodError::check("IDirect3DDevice9::CreateQuery", hr)?;
Ok(unsafe { Query::from_raw(query) })
}
fn create_render_target(&self, width: u32, height: u32, format: Format, multi_sample: MultiSample, multi_sample_quality: u32, lockable: bool, _shared_handle: impl SharedHandleParam) -> Result<Surface, MethodError> {
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().CreateRenderTarget(width, height, format.into(), multi_sample.into(), multi_sample_quality, lockable.into(), &mut surface, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateRenderTarget", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn create_state_block(&self, type_: StateBlockType) -> Result<StateBlock, MethodError> {
let mut sb = null_mut();
let hr = unsafe { self.as_winapi().CreateStateBlock(type_.into(), &mut sb) };
MethodError::check("IDirect3DDevice9::CreateStateBlock", hr)?;
Ok(unsafe { StateBlock::from_raw(sb) })
}
fn create_texture(&self, width: u32, height: u32, levels: u32, usage: impl Into<Usage>, format: impl Into<Format>, pool: impl Into<Pool>, _shared_handle: impl SharedHandleParam) -> Result<Texture, MethodError> {
let mut texture = null_mut();
let hr = unsafe { self.as_winapi().CreateTexture(width, height, levels, usage.into().into(), format.into().into(), pool.into().into(), &mut texture, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateTexture", hr)?;
Ok(unsafe { Texture::from_raw(texture) })
}
fn create_vertex_buffer(&self, length: u32, usage: impl Into<Usage>, fvf: impl Into<FVF>, pool: impl Into<Pool>, _shared_handle: impl SharedHandleParam) -> Result<VertexBuffer, MethodError> {
if length > MAX_BUFFER_ALLOC { return Err(MethodError("Device::create_vertex_buffer", THINERR::ALLOC_OVERFLOW)); }
let mut buffer = null_mut();
let hr = unsafe { self.as_winapi().CreateVertexBuffer(length, usage.into().into(), fvf.into().into(), pool.into().into(), &mut buffer, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateVertexBuffer", hr)?;
Ok(unsafe { VertexBuffer::from_raw(buffer) })
}
fn create_vertex_declaration(&self, elements: &[VertexElement]) -> Result<VertexDeclaration, MethodError> {
let end = elements.last().ok_or(MethodError("Device::create_vertex_declaration", D3DERR::INVALIDCALL))?;
if *end != VertexElement::END { return Err(MethodError("Device::create_vertex_declaration", D3DERR::INVALIDCALL)); }
let mut vd = null_mut();
let hr = unsafe { self.as_winapi().CreateVertexDeclaration(elements.as_ptr().cast(), &mut vd) };
MethodError::check("IDirect3DDevice9::CreateVertexDeclaration", hr)?;
Ok(unsafe { VertexDeclaration::from_raw(vd) })
}
unsafe fn create_vertex_shader(&self, function: &[u32]) -> Result<VertexShader, MethodError> {
let mut shader = null_mut();
let hr = self.as_winapi().CreateVertexShader(function.as_ptr(), &mut shader);
MethodError::check("IDirect3DDevice9::CreateVertexShader", hr)?;
Ok(VertexShader::from_raw(shader))
}
fn create_volume_texture(&self, width: u32, height: u32, depth: u32, levels: u32, usage: impl Into<Usage>, format: impl Into<Format>, pool: impl Into<Pool>, _shared_handle: impl SharedHandleParam) -> Result<VolumeTexture, MethodError> {
let mut volumetexture = null_mut();
let hr = unsafe { self.as_winapi().CreateVolumeTexture(width, height, depth, levels, usage.into().into(), format.into().into(), pool.into().into(), &mut volumetexture, null_mut()) };
MethodError::check("IDirect3DDevice9::CreateVolumeTexture", hr)?;
Ok(unsafe { VolumeTexture::from_raw(volumetexture) })
}
unsafe fn draw_indexed_primitive(&self, primitive_type: PrimitiveType, base_vertex_index: i32, min_vertex_index: u32, num_verticies: u32, start_index: u32, primitive_count: u32) -> Result<(), MethodError> {
let hr = self.as_winapi().DrawIndexedPrimitive(primitive_type.into(), base_vertex_index, min_vertex_index, num_verticies, start_index, primitive_count);
MethodError::check("IDirect3DDevice9::DrawIndexedPrimitive", hr)
}
unsafe fn draw_indexed_primitive_up(&self, primitive_type: PrimitiveType, min_vertex_index: u32, num_verticies: u32, primitive_count: u32, index_data: impl IndexData, vertex_stream_zero: impl VertexStreamData) -> Result<(), MethodError> {
let hr = self.as_winapi().DrawIndexedPrimitiveUP(primitive_type.into(), min_vertex_index, num_verticies, primitive_count, index_data.ptr(), index_data.format().into(), vertex_stream_zero.ptr(), vertex_stream_zero.stride());
MethodError::check("IDirect3DDevice9::DrawIndexedPrimitiveUP", hr)
}
unsafe fn draw_primitive(&self, primitive_type: PrimitiveType, start_vertex: u32, primitive_count: u32) -> Result<(), MethodError> {
let hr = self.as_winapi().DrawPrimitive(primitive_type.into(), start_vertex, primitive_count);
MethodError::check("IDirect3DDevice9::DrawPrimitive", hr)
}
unsafe fn draw_primitive_up(&self, primitive_type: PrimitiveType, primitive_count: u32, vertex_stream_zero: impl VertexStreamData) -> Result<(), MethodError> {
let hr = self.as_winapi().DrawPrimitiveUP(primitive_type.into(), primitive_count, vertex_stream_zero.ptr(), vertex_stream_zero.stride());
MethodError::check("IDirect3DDevice9::DrawPrimitiveUP", hr)
}
fn end_scene(&self) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().EndScene() };
MethodError::check("IDirect3DDevice9::EndScene", hr)
}
fn end_state_block(&self) -> Result<StateBlock, MethodError> {
let mut sb = null_mut();
let hr = unsafe { self.as_winapi().EndStateBlock(&mut sb) };
MethodError::check("IDirect3DDevice9::EndStateBlock", hr)?;
Ok(unsafe { StateBlock::from_raw(sb) })
}
fn evict_managed_resources(&self) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().EvictManagedResources() };
MethodError::check("IDirect3DDevice9::EvictManagedResources", hr)
}
fn get_available_texture_mem(&self) -> u32 {
unsafe { self.as_winapi().GetAvailableTextureMem() }
}
fn get_back_buffer(&self, swap_chain: u32, back_buffer: u32, type_: BackBufferType) -> Result<Surface, MethodError> {
let mut surface = null_mut();
let hr = unsafe { self.as_winapi().GetBackBuffer(swap_chain, back_buffer, type_.into(), &mut surface) };
MethodError::check("IDirect3DDevice9::GetBackBuffer", hr)?;
Ok(unsafe { Surface::from_raw(surface) })
}
fn get_clip_plane(&self, index: u32) -> Result<[f32; 4], MethodError> {
let mut plane = [0.0, 0.0, 0.0, 0.0];
let hr = unsafe { self.as_winapi().GetClipPlane(index, plane.as_mut_ptr()) };
MethodError::check("IDirect3DDevice9::GetClipPlane", hr)?;
Ok(plane)
}
fn get_clip_status(&self) -> Result<ClipStatus, MethodError> {
let mut status = D3DCLIPSTATUS9 { ClipUnion: 0, ClipIntersection: 0 };
let hr = unsafe { self.as_winapi().GetClipStatus(&mut status) };
MethodError::check("IDirect3DDevice9::GetClipStatus", hr)?;
Ok(ClipStatus::from_unchecked(status))
}
fn get_creation_parameters(&self) -> Result<D3DDEVICE_CREATION_PARAMETERS, MethodError> {
let mut dcp = unsafe { std::mem::zeroed::<D3DDEVICE_CREATION_PARAMETERS>() };
let hr = unsafe { self.as_winapi().GetCreationParameters(&mut dcp) };
MethodError::check("IDirect3DDevice9::GetCreationParameters", hr)?;
Ok(dcp)
}
fn get_current_texture_palette(&self) -> Result<u32, MethodError> {
let mut pal = 0;
let hr = unsafe { self.as_winapi().GetCurrentTexturePalette(&mut pal) };
MethodError::check("IDirect3DDevice9::GetCurrentTexturePalette", hr)?;
Ok(pal)
}
fn get_depth_stencil_surface(&self) -> Result<Option<Surface>, MethodError> {
let mut ds = null_mut();
let hr = unsafe { self.as_winapi().GetDepthStencilSurface(&mut ds) };
if hr == D3DERR::NOTFOUND {
Ok(None)
} else {
MethodError::check("IDirect3DDevice9::GetDepthStencilSurface", hr)?;
Ok(unsafe { Surface::from_raw_opt(ds) })
}
}
fn get_device_caps(&self) -> Result<Caps, MethodError> {
let mut caps = Caps::zeroed();
let hr = unsafe { self.as_winapi().GetDeviceCaps(&mut *caps) };
MethodError::check("IDirect3DDevice9::GetDeviceCaps", hr)?;
Ok(caps)
}
fn get_direct3d(&self) -> Result<Direct3D, MethodError> {
let mut d3d = null_mut();
let hr = unsafe { self.as_winapi().GetDirect3D(&mut d3d) };
MethodError::check("IDirect3DDevice9::GetDirect3D", hr)?;
Ok(unsafe { Direct3D::from_raw(d3d) })
}
fn get_display_mode(&self, swap_chain: u32) -> Result<DisplayMode, MethodError> {
let mut dm = DisplayMode::default();
let hr = unsafe { self.as_winapi().GetDisplayMode(swap_chain, &mut *dm) };
MethodError::check("IDirect3DDevice9::GetDisplayMode", hr)?;
Ok(dm)
}
fn get_front_buffer_data(&self, swap_chain: u32, surface: &Surface) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().GetFrontBufferData(swap_chain, surface.as_raw()) };
MethodError::check("IDirect3DDevice9::GetFrontBufferData", hr)
}
fn get_fvf(&self) -> Result<FVF, MethodError> {
let mut fvf = FVF::None;
let hr = unsafe { self.as_winapi().GetFVF(&mut *fvf) };
MethodError::check("IDirect3DDevice9::GetFVF", hr)?;
Ok(fvf)
}
fn get_gamma_ramp(&self, swap_chain: u32) -> D3DGAMMARAMP {
let mut ramp = unsafe { std::mem::zeroed::<D3DGAMMARAMP>() };
let _nohr : () = unsafe { self.as_winapi().GetGammaRamp(swap_chain, &mut ramp) };
ramp
}
fn get_indices(&self) -> Result<Option<IndexBuffer>, MethodError> {
let mut buffer = null_mut();
let hr = unsafe { self.as_winapi().GetIndices(&mut buffer) };
MethodError::check("IDirect3DDevice9::GetIndices", hr)?;
Ok(unsafe { IndexBuffer::from_raw_opt(buffer) })
}
fn get_light(&self, index: u16) -> Result<Light, MethodError> {
self.get_light_32(index.into())
}
fn get_light_32(&self, index: u32) -> Result<Light, MethodError> {
let mut light = Light::default();
let hr = unsafe { self.as_winapi().GetLight(index, &mut *light) };
MethodError::check("IDirect3DDevice9::GetLight", hr)?;
Ok(light)
}
fn get_light_enable(&self, index: u16) -> Result<bool, MethodError> {
self.get_light_enable_32(index.into())
}
fn get_light_enable_32(&self, index: u32) -> Result<bool, MethodError> {
let mut enable = 0;
let hr = unsafe { self.as_winapi().GetLightEnable(index, &mut enable) };
MethodError::check("IDirect3DDevice9::GetLightEnable", hr)?;
Ok(enable != 0)
}
fn get_material(&self) -> Result<Material, MethodError> {
let mut material = Material::default();
let hr = unsafe { self.as_winapi().GetMaterial(&mut *material) };
MethodError::check("IDirect3DDevice9::GetMaterial", hr)?;
Ok(material)
}
fn get_npatch_mode(&self) -> f32 {
unsafe { self.as_winapi().GetNPatchMode() }
}
unsafe fn get_palette_entries(&self, palette_number: u32) -> Result<[Color; 256], MethodError> {
let mut colors = [Color::argb(0); 256];
let hr = self.as_winapi().GetPaletteEntries(palette_number, colors.as_mut_ptr().cast());
MethodError::check("IDirect3DDevice9::GetPaletteEntries", hr)?;
Ok(colors)
}
fn get_pixel_shader(&self) -> Result<PixelShader, MethodError> {
let mut shader = null_mut();
let hr = unsafe { self.as_winapi().GetPixelShader(&mut shader) };
MethodError::check("IDirect3DDevice9::GetPixelShader", hr)?;
Ok(unsafe { PixelShader::from_raw(shader) })
}
fn get_render_target(&self, render_target_index: u32) -> Result<Option<Surface>, MethodError> {
let mut rt = null_mut();
let hr = unsafe { self.as_winapi().GetRenderTarget(render_target_index, &mut rt) };
if hr == D3DERR::NOTFOUND {
Ok(None)
} else {
MethodError::check("IDirect3DDevice9::GetRenderTarget", hr)?;
Ok(unsafe { Surface::from_raw_opt(rt) })
}
}
fn get_render_target_data(&self, render_target: &Surface, dest_surface: &Surface) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().GetRenderTargetData(render_target.as_raw(), dest_surface.as_raw()) };
MethodError::check("IDirect3DDevice9::GetRenderTargetData", hr)
}
fn get_stream_source(&self, stream_number: u32) -> Result<(Option<VertexBuffer>, u32, u32), MethodError> {
let mut buffer = null_mut();
let mut offset = 0;
let mut stride = 0;
let hr = unsafe { self.as_winapi().GetStreamSource(stream_number, &mut buffer, &mut offset, &mut stride) };
MethodError::check("IDirect3DDevice9::GetStreamSource", hr)?;
let buffer = unsafe { VertexBuffer::from_raw_opt(buffer) };
Ok((buffer, offset, stride))
}
fn get_stream_source_freq(&self, stream_number: u32) -> Result<StreamSource, MethodError> {
let mut freq = 0;
let hr = unsafe { self.as_winapi().GetStreamSourceFreq(stream_number, &mut freq) };
MethodError::check("IDirect3DDevice9::GetStreamSourceFreq", hr)?;
Ok(StreamSource::from_unchecked(freq))
}
unsafe fn get_texture(&self, stage: u32) -> Result<Option<BaseTexture>, MethodError> {
let mut texture = null_mut();
let hr = self.as_winapi().GetTexture(stage, &mut texture);
MethodError::check("IDirect3DDevice9::GetTexture", hr)?;
Ok(BaseTexture::from_raw_opt(texture))
}
fn get_vertex_shader(&self) -> Result<VertexShader, MethodError> {
let mut shader = null_mut();
let hr = unsafe { self.as_winapi().GetVertexShader(&mut shader) };
MethodError::check("IDirect3DDevice9::GetVertexShader", hr)?;
Ok(unsafe { VertexShader::from_raw(shader) })
}
fn get_viewport(&self) -> Result<Viewport, MethodError> {
let mut viewport = Viewport::default();
let hr = unsafe { self.as_winapi().GetViewport(&mut *viewport) };
MethodError::check("IDirect3DDevice9::GetViewport", hr)?;
Ok(viewport)
}
fn light_enable(&self, index: u16, enable: bool) -> Result<(), MethodError> {
unsafe { self.light_enable_32_unchecked(index.into(), enable) }
}
unsafe fn light_enable_32_unchecked(&self, index: u32, enable: bool) -> Result<(), MethodError> {
let hr = self.as_winapi().LightEnable(index, enable.into());
MethodError::check("IDirect3DDevice9::LightEnable", hr)
}
fn present<'r>(&self, source_rect: impl IntoRectOrFull, dest_rect: impl IntoRectOrFull, dest_window_override: impl AsHWND, dirty_region: impl Into<Option<&'r RgnData>>) -> Result<(), MethodError> {
let source_rect = source_rect.into_rect();
let dest_rect = dest_rect.into_rect();
let hwnd = dest_window_override.as_hwnd();
let dirty_region = dirty_region.into();
let source_rect = source_rect .map_or(null(), |r| &*r).cast();
let dest_rect = dest_rect .map_or(null(), |r| &*r).cast();
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("IDirect3DDevice9Ext::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.iType != RDH_RECTANGLES { return Err(MethodError("IDirect3DDevice9Ext::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.nCount as usize > dr.buffer.len() { return Err(MethodError("IDirect3DDevice9Ext::present", THINERR::INVALID_STRUCT_FIELD)); }
if dr.rdh.nRgnSize as usize > std::mem::size_of_val(dr) { return Err(MethodError("IDirect3DDevice9Ext::present", THINERR::INVALID_STRUCT_FIELD)); }
let dr : *const RgnData = dr;
dr.cast()
},
};
let hr = unsafe { self.as_winapi().Present(source_rect, dest_rect, hwnd, dirty_region) };
MethodError::check("IDirect3DDevice9::Present", hr)
}
unsafe fn reset(&self, presentation_parameters: &mut D3DPRESENT_PARAMETERS) -> Result<(), MethodError> {
let hr = self.as_winapi().Reset(presentation_parameters);
MethodError::check("IDirect3DDevice9::Reset", hr)
}
fn set_depth_stencil_surface(&self, depth_stencil_surface: Option<&Surface>) -> Result<(), MethodError> {
let ds = depth_stencil_surface.map_or(null_mut(), |ds| ds.as_raw());
let hr = unsafe { self.as_winapi().SetDepthStencilSurface(ds) };
MethodError::check("IDirect3DDevice9::SetDepthStencilSurface", hr)
}
fn set_fvf(&self, fvf: impl Into<FVF>) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetFVF(fvf.into().into()) };
MethodError::check("IDirect3DDevice9::SetFVF", hr)
}
fn set_gamma_ramp(&self, swap_chain: u32, flags: impl Into<SGR>, ramp: &D3DGAMMARAMP) {
let _nohr : () = unsafe { self.as_winapi().SetGammaRamp(swap_chain, flags.into().into(), ramp) };
}
fn set_indices<'ib>(&self, index_data: impl Into<Option<&'ib IndexBuffer>>) -> Result<(), MethodError> {
let ptr = match index_data.into() {
None => null_mut(),
Some(ib) => { ib.check_compatible_with(self, "Device::set_indices")?; ib.as_raw() }
};
let hr = unsafe { self.as_winapi().SetIndices(ptr) };
MethodError::check("IDirect3DDevice9::SetIndices", hr)
}
fn set_light(&self, index: u16, light: impl Into<Light>) -> Result<(), MethodError> {
unsafe { self.set_light_32_unchecked(index.into(), light.into()) }
}
unsafe fn set_light_32_unchecked(&self, index: u32, light: impl Into<Light>) -> Result<(), MethodError> {
let light = light.into();
let hr = self.as_winapi().SetLight(index, &*light);
MethodError::check("IDirect3DDevice9::SetLight", hr)
}
fn set_material(&self, material: impl Into<Material>) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetMaterial(&*material.into()) };
MethodError::check("IDirect3DDevice9::SetMaterial", hr)
}
fn set_npatch_mode(&self, mode: f32) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetNPatchMode(mode) };
MethodError::check("IDirect3DDevice9::SetNPatchMode", hr)
}
fn set_palette_entries(&self, palette_number: u32, entries: &[Color; 256]) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetPaletteEntries(palette_number, entries.as_ptr().cast()) };
MethodError::check("IDirect3DDevice9::SetPaletteEntries", hr)
}
fn set_pixel_shader<'sh>(&self, pixel_shader: impl Into<Option<&'sh PixelShader>>) -> Result<(), MethodError> {
let pixel_shader = pixel_shader.into();
let ps = pixel_shader.map_or(null_mut(), |ps| ps.as_raw());
let hr = unsafe { self.as_winapi().SetPixelShader(ps) };
MethodError::check("IDirect3DDevice9::SetPixelShader", hr)
}
fn set_pixel_shader_constant_b(&self, start_register: u32, constant_data: &[bool32]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_pixel_shader_constant_b", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetPixelShaderConstantB(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetPixelShaderConstantB", hr)
}
fn set_pixel_shader_constant_f(&self, start_register: u32, constant_data: &[f32]) -> Result<(), MethodError> {
let n = constant_data.len();
if (n % 4) != 0 { return Err(MethodError("Device::set_pixel_shader_constant_f", D3DERR::INVALIDCALL)); }
let n : u32 = (n/4).try_into().map_err(|_| MethodError("Device::set_pixel_shader_constant_f", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetPixelShaderConstantF(start_register, constant_data.as_ptr(), n) };
MethodError::check("IDirect3DDevice9::SetPixelShaderConstantF", hr)
}
fn set_pixel_shader_constant_fv(&self, start_register: u32, constant_data: &[[f32; 4]]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_pixel_shader_constant_fv", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetPixelShaderConstantF(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetPixelShaderConstantF", hr)
}
fn set_pixel_shader_constant_i(&self, start_register: u32, constant_data: &[i32]) -> Result<(), MethodError> {
let n = constant_data.len();
if (n % 4) != 0 { return Err(MethodError("Device::set_pixel_shader_constant_i", D3DERR::INVALIDCALL)); }
let n : u32 = (n/4).try_into().map_err(|_| MethodError("Device::set_pixel_shader_constant_i", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetPixelShaderConstantI(start_register, constant_data.as_ptr(), n) };
MethodError::check("IDirect3DDevice9::SetPixelShaderConstantI", hr)
}
fn set_pixel_shader_constant_iv(&self, start_register: u32, constant_data: &[[i32; 4]]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_pixel_shader_constant_iv", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetPixelShaderConstantI(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetPixelShaderConstantI", hr)
}
fn set_render_state_untyped(&self, state: impl Into<d3d9::RenderStateType>, value: impl Into<u32>) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetRenderState(state.into().into(), value.into()) };
MethodError::check("IDirect3DDevice9::SetRenderState", hr)
}
fn set_render_target(&self, render_target_index: u32, render_target: Option<&Surface>) -> Result<(), MethodError> {
let rt = render_target.map_or(null_mut(), |rt| rt.as_raw());
let hr = unsafe { self.as_winapi().SetRenderTarget(render_target_index, rt) };
MethodError::check("IDirect3DDevice9::SetRenderTarget", hr)
}
unsafe fn set_sampler_state_unchecked(&self, sampler: u32, ty: SamplerStateType, value: impl Into<u32>) -> Result<(), MethodError> {
let hr = self.as_winapi().SetSamplerState(sampler, ty.into(), value.into());
MethodError::check("IDirect3DDevice9::SetSamplerState", hr)
}
fn set_stream_source<'b>(&self, stream_number: u32, stream_data: impl Into<Option<&'b VertexBuffer>>, offset_in_bytes: u32, stride: u32) -> Result<(), MethodError> {
let stream_data = match stream_data.into() {
None => null_mut(),
Some(sd) => { sd.check_compatible_with(self, "Device::set_stream_source")?; sd.as_raw() },
};
let hr = unsafe { self.as_winapi().SetStreamSource(stream_number, stream_data, offset_in_bytes, stride) };
MethodError::check("IDirect3DDevice9::SetStreamSource", hr)
}
fn set_stream_source_freq(&self, stream_number: u32, setting: impl Into<StreamSource>) -> Result<(), MethodError> {
let setting = setting.into().into();
let hr = unsafe { self.as_winapi().SetStreamSourceFreq(stream_number, setting) };
MethodError::check("IDirect3DDevice9::SetStreamSourceFreq", hr)
}
unsafe fn set_texture<'t>(&self, stage: u32, texture: impl Into<Option<&'t BaseTexture>>) -> Result<(), MethodError> {
let texture = texture.into();
let texture = texture.map_or(null_mut(), |t| t.as_raw());
let hr = self.as_winapi().SetTexture(stage, texture);
MethodError::check("IDirect3DDevice9::SetTexture", hr)
}
fn set_transform(&self, ts: impl Into<TransformStateType>, matrix: impl Into<Matrix>) -> Result<(), MethodError> {
let hr = unsafe { self.as_winapi().SetTransform(ts.into().into(), &matrix.into().into()) };
MethodError::check("IDirect3DDevice9::SetTransform", hr)
}
fn set_vertex_declaration<'d>(&self, decl: impl Into<Option<&'d VertexDeclaration>>) -> Result<(), MethodError> {
let decl = decl.into();
let decl = decl.map_or(null_mut(), |d| d.as_raw());
let hr = unsafe { self.as_winapi().SetVertexDeclaration(decl) };
MethodError::check("IDirect3DDevice9::SetVertexDeclaration", hr)
}
fn set_vertex_shader<'sh>(&self, vertex_shader: impl Into<Option<&'sh VertexShader>>) -> Result<(), MethodError> {
let vertex_shader = vertex_shader.into();
let ps = vertex_shader.map_or(null_mut(), |ps| ps.as_raw());
let hr = unsafe { self.as_winapi().SetVertexShader(ps) };
MethodError::check("IDirect3DDevice9::SetVertexShader", hr)
}
fn set_vertex_shader_constant_b(&self, start_register: u32, constant_data: &[bool32]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_vertex_shader_constant_b", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetVertexShaderConstantB(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetVertexShaderConstantB", hr)
}
fn set_vertex_shader_constant_f(&self, start_register: u32, constant_data: &[f32]) -> Result<(), MethodError> {
let n = constant_data.len();
if (n % 4) != 0 { return Err(MethodError("Device::set_vertex_shader_constant_f", D3DERR::INVALIDCALL)); }
let n : u32 = (n/4).try_into().map_err(|_| MethodError("Device::set_vertex_shader_constant_f", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetVertexShaderConstantF(start_register, constant_data.as_ptr(), n) };
MethodError::check("IDirect3DDevice9::SetVertexShaderConstantF", hr)
}
fn set_vertex_shader_constant_fv(&self, start_register: u32, constant_data: &[[f32; 4]]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_vertex_shader_constant_fv", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetVertexShaderConstantF(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetVertexShaderConstantF", hr)
}
fn set_vertex_shader_constant_i(&self, start_register: u32, constant_data: &[i32]) -> Result<(), MethodError> {
let n = constant_data.len();
if (n % 4) != 0 { return Err(MethodError("Device::set_vertex_shader_constant_i", D3DERR::INVALIDCALL)); }
let n : u32 = (n/4).try_into().map_err(|_| MethodError("Device::set_vertex_shader_constant_i", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetVertexShaderConstantI(start_register, constant_data.as_ptr(), n) };
MethodError::check("IDirect3DDevice9::SetVertexShaderConstantI", hr)
}
fn set_vertex_shader_constant_iv(&self, start_register: u32, constant_data: &[[i32; 4]]) -> Result<(), MethodError> {
let n : u32 = constant_data.len().try_into().map_err(|_| MethodError("Device::set_vertex_shader_constant_iv", D3DERR::INVALIDCALL))?;
let hr = unsafe { self.as_winapi().SetVertexShaderConstantI(start_register, constant_data.as_ptr().cast(), n) };
MethodError::check("IDirect3DDevice9::SetVertexShaderConstantI", hr)
}
fn set_viewport(&self, viewport: impl Into<Viewport>) -> Result<(), MethodError> {
let viewport = viewport.into();
let hr = unsafe { self.as_winapi().SetViewport(&*viewport) };
MethodError::check("IDirect3DDevice9::SetViewport", hr)
}
}
impl<T: AsSafe<IDirect3DDevice9>> IDirect3DDevice9Ext for T {}
#[repr(C)]
pub struct RgnData {
pub(crate) rdh: RGNDATAHEADER,
pub(crate) buffer: [Rect],
}
#[cfg(test)] mod tests {
use dev::d3d9::*;
#[test] fn begin_end_scene() {
let device = device_test();
assert_eq!(D3DERR::INVALIDCALL, device.end_scene());
device.begin_scene().unwrap();
device.end_scene().unwrap();
assert_eq!(D3DERR::INVALIDCALL, device.end_scene());
device.begin_scene().unwrap();
assert_eq!(D3DERR::INVALIDCALL, device.begin_scene());
device.end_scene().unwrap();
assert_eq!(D3DERR::INVALIDCALL, device.end_scene());
device.begin_scene().unwrap();
for _ in 0..1000 { assert_eq!(D3DERR::INVALIDCALL, device.begin_scene()); }
device.end_scene().unwrap();
for _ in 0..1000 { assert_eq!(D3DERR::INVALIDCALL, device.end_scene()); }
}
#[test] fn present() {
let device = device_test_pp(false, |pp, _| pp.SwapEffect = SwapEffect::Copy.into()).unwrap();
device.present(.., .., (), None).unwrap();
for rect in [
(0, 0) .. (1, 1),
(-100, -100) .. (100, 100),
(100, 100) .. (-100, -100),
(-1000, -1000) .. (1000, 1000),
(1000, 1000) .. (-1000, -1000),
(-100000, -100000) .. (100000, 100000),
(0, 0) .. (100000, 100000),
(0, 0) .. (i32::MAX, i32::MAX),
(i32::MIN, i32::MIN) .. (i32::MAX, i32::MAX),
(i32::MAX, i32::MAX) .. (i32::MIN, i32::MIN),
].iter().cloned() {
let rect = Rect::from(rect);
device.present(rect, rect, (), None).unwrap();
}
}
}