diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_state.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_state.rs new file mode 100644 index 0000000000..7ebff395df --- /dev/null +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/gem_state.rs @@ -0,0 +1,186 @@ +use log::info; + +use super::super::gtt::IntelGtt; +use crate::driver::Result; + +const GEN9_RENDER_STATE_SIZE: usize = 4096; +const GEN8_RENDER_STATE_SIZE: usize = 2048; + +pub struct RenderState { + buffer: Vec, + gpu_addr: u64, + initialized: bool, +} + +impl RenderState { + pub fn new() -> Self { + Self { buffer: Vec::new(), gpu_addr: 0, initialized: false } + } + + pub fn init_gen9(&mut self, gtt: &mut IntelGtt) -> Result<()> { + self.buffer.clear(); + + self.buffer.extend_from_slice(&[ + 0x1100_0001, // MI_LOAD_REGISTER_IMM + 0x2244, // register offset + 0x0000_0001, // value + ]); + + self.buffer.extend_from_slice(&[ + 0x1100_0001, // MI_LOAD_REGISTER_IMM + 0x20D8, // STATE_BASE_ADDRESS + 0x0000_0001, // General State Base Address + 0xFFFF_F001, // General State Base Address Upper + 0xFFFF_0001, // Dynamic State Base Address + 0xFFFF_F001, // Dynamic State Base Address Upper + 0xFFFF_0001, // Indirect Object Base Address + 0xFFFF_F001, // Indirect Object Base Address Upper + 0xFFFF_0001, // Instruction Base Address + 0xFFFF_F001, // Instruction Base Address Upper + ]); + + self.buffer.extend_from_slice(&[ + 0x6101_0008, // 3DSTATE_CC_STATE_POINTERS + 0x0000_0001, + 0x0000_0001, + ]); + + self.buffer.extend_from_slice(&[ + 0x0500_0000, // MI_BATCH_BUFFER_END + ]); + + let aligned_size = ((self.buffer.len() * 4 + 4095) / 4096) * 4096; + self.gpu_addr = gtt.alloc_range(aligned_size as u64)?; + gtt.map_range(self.gpu_addr, 0, aligned_size as u64, (1 << 0) | (1 << 1))?; + + self.initialized = true; + info!("redox-drm-intel: Gen9 render state initialized at {:#x} ({} dwords)", self.gpu_addr, self.buffer.len()); + Ok(()) + } + + pub fn init_gen8(&mut self, gtt: &mut IntelGtt) -> Result<()> { + self.buffer.extend_from_slice(&[ + 0x1100_0001, 0x2244, 0x0000_0001, + ]); + self.buffer.extend_from_slice(&[ + 0x0500_0000, + ]); + + let aligned_size = ((self.buffer.len() * 4 + 4095) / 4096) * 4096; + self.gpu_addr = gtt.alloc_range(aligned_size as u64)?; + gtt.map_range(self.gpu_addr, 0, aligned_size as u64, (1 << 0) | (1 << 1))?; + + self.initialized = true; + info!("redox-drm-intel: Gen8 render state initialized at {:#x}", self.gpu_addr); + Ok(()) + } + + pub fn is_initialized(&self) -> bool { self.initialized } + pub fn gpu_addr(&self) -> u64 { self.gpu_addr } + pub fn dword_count(&self) -> usize { self.buffer.len() } +} + +pub struct FenceRegisterState { + registers: [Option; 32], +} + +#[derive(Clone, Copy, Debug)] +pub struct FenceReg { + pub handle: u32, + pub start: u64, + pub size: u64, + pub tiled: bool, + pub pitch: u32, +} + +impl FenceRegisterState { + pub fn new() -> Self { Self { registers: [None; 32] } } + + pub fn allocate(&mut self, handle: u32, start: u64, size: u64, tiled: bool, pitch: u32) -> Option { + for i in 0..32 { + if self.registers[i].is_none() { + self.registers[i] = Some(FenceReg { handle, start, size, tiled, pitch }); + return Some(i as u32); + } + } + None + } + + pub fn release(&mut self, reg: u32) -> Result<()> { + if (reg as usize) < 32 { self.registers[reg as usize] = None; } + Ok(()) + } + + pub fn get(&self, reg: u32) -> Option<&FenceReg> { + self.registers.get(reg as usize).and_then(|r| r.as_ref()) + } + + pub fn used_count(&self) -> u32 { + self.registers.iter().filter(|r| r.is_some()).count() as u32 + } + + pub fn find_by_handle(&self, handle: u32) -> Option { + for (i, reg) in self.registers.iter().enumerate() { + if let Some(r) = reg { if r.handle == handle { return Some(i as u32); } } + } + None + } +} + +pub struct FrameBufferCompressionState { + active_buffers: std::collections::BTreeMap, + compressed_bytes: u64, +} + +#[derive(Clone, Debug)] +pub struct FbcBuffer { + pub gem_handle: u32, + pub width: u16, + pub height: u16, + pub stride: u32, + pub compressed: bool, + pub cfb_offset: u64, + pub cfb_size: u64, +} + +impl FrameBufferCompressionState { + pub fn new() -> Self { + Self { active_buffers: std::collections::BTreeMap::new(), compressed_bytes: 0 } + } + + pub fn register(&mut self, handle: u32, width: u16, height: u16, stride: u32) { + self.active_buffers.insert(handle, FbcBuffer { + gem_handle: handle, width, height, stride, + compressed: false, cfb_offset: 0, cfb_size: 0, + }); + } + + pub fn unregister(&mut self, handle: u32) { + self.active_buffers.remove(&handle); + } + + pub fn mark_compressed(&mut self, handle: u32, cfb_offset: u64, cfb_size: u64) { + if let Some(buf) = self.active_buffers.get_mut(&handle) { + buf.compressed = true; + buf.cfb_offset = cfb_offset; + buf.cfb_size = cfb_size; + self.compressed_bytes += cfb_size; + } + } + + pub fn mark_uncompressed(&mut self, handle: u32) { + if let Some(buf) = self.active_buffers.get_mut(&handle) { + if buf.compressed { + self.compressed_bytes -= buf.cfb_size; + buf.compressed = false; + } + } + } + + pub fn is_compressed(&self, handle: u32) -> bool { + self.active_buffers.get(&handle).map_or(false, |b| b.compressed) + } + + pub fn compressed_bytes(&self) -> u64 { self.compressed_bytes } + pub fn active_count(&self) -> usize { self.active_buffers.len() } +} diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs index 740b481d8b..46ef52181f 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/gem/mod.rs @@ -13,6 +13,7 @@ pub mod gem_object; pub mod gem_pages; pub mod gem_region; pub mod gem_request; +pub mod gem_state; pub mod gem_stolen; pub mod gem_tiling; pub mod gem_ttm; @@ -33,6 +34,7 @@ pub use gem_object::{CacheLevel, GemHandle, GemObject, GemObjectManager, MemoryR pub use gem_pages::{PageManager, TtmMoveManager}; pub use gem_region::MemoryRegion; pub use gem_request::{EngineClass, GemRequest, GemStatistics, RequestManager, Scheduler}; +pub use gem_state::{FbcBuffer, FenceReg, FenceRegisterState, FrameBufferCompressionState, RenderState}; pub use gem_stolen::{ShrinkerManager, StolenMemoryManager}; pub use gem_tiling::{FenceRegisterManager, TilingConfig, TilingManager, TilingMode}; pub use gem_ttm::{Migration, PowerManager, TtmManager};