diff --git a/README.md b/README.md index 7466543..c2cb762 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ fn main() { - `drain_events()` – Iterator über `Event` (`Key`, `Char`, `MouseMove`, `MouseBtn`, `Resize`, `CloseRequested`). - `framebuffer_mut()` – `&mut [u8]` der Länge `w*h`, je Pixel ein Paletten-Index. +- `palette_mut()` / `palette()` – `&mut [[u8; 3]; 256]` bzw. `&[...]`; Schreibzugriff + markiert die Palette dirty, der nächste `present()` lädt sie hoch. - `present()` – Frame auf das Fenster bringen. - `should_close()` / `request_close()`. - `set_mouse_visible(bool)` – Cursor anzeigen oder verstecken (freie Bewegung). @@ -91,3 +93,12 @@ pitch += dy * sensitivity; `palette::RGB332` ist als Default eingebaut. Eigene Paletten sind ein `[[u8; 3]; 256]` (RGB pro Index) und werden über `PlatformConfig::palette` übergeben. + +Zur Laufzeit kann die Palette über `palette_mut()` modifiziert werden — einzelne +Einträge oder die komplette Tabelle. Der Upload passiert automatisch im nächsten +`present()`: + +```rust +p.palette_mut()[42] = [255, 0, 0]; // Slot 42 → rot +p.present(); +``` diff --git a/src/lib.rs b/src/lib.rs index 1273b33..9a4d1b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,8 +82,9 @@ pub struct Platform { bind_group: wgpu::BindGroup, pipeline: wgpu::RenderPipeline, index_tex: wgpu::Texture, - #[allow(dead_code)] palette_tex: wgpu::Texture, + palette: [[u8; 3]; 256], + palette_dirty: bool, params_buf: wgpu::Buffer, params: Params, surface: wgpu::Surface<'static>, @@ -215,7 +216,9 @@ impl Platform { }); let mut platform = Self { - bind_group, pipeline, index_tex, palette_tex, params_buf, params, + bind_group, pipeline, index_tex, palette_tex, + palette: cfg.palette, palette_dirty: false, + params_buf, params, surface, config: surface_config, device, queue, instance, window, events, glfw, framebuffer: vec![0u8; (src_w * src_h) as usize], @@ -285,7 +288,35 @@ impl Platform { pub fn framebuffer_mut(&mut self) -> &mut [u8] { &mut self.framebuffer } pub fn framebuffer_size(&self) -> (u32, u32) { self.framebuffer_size } + /// Liefert &mut auf die 256-Einträge-Palette. Setzt pessimistisch ein + /// Dirty-Flag — der nächste `present()` lädt die Palette neu hoch. + pub fn palette_mut(&mut self) -> &mut [[u8; 3]; 256] { + self.palette_dirty = true; + &mut self.palette + } + pub fn palette(&self) -> &[[u8; 3]; 256] { &self.palette } + pub fn present(&mut self) { + if self.palette_dirty { + let rgba: [u8; 256 * 4] = { + let mut buf = [0u8; 256 * 4]; + for (i, [r, g, b]) in self.palette.iter().enumerate() { + buf[i * 4] = *r; + buf[i * 4 + 1] = *g; + buf[i * 4 + 2] = *b; + buf[i * 4 + 3] = 255; + } + buf + }; + self.queue.write_texture( + wgpu::TexelCopyTextureInfoBase { texture: &self.palette_tex, mip_level: 0, origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All }, + &rgba, + wgpu::TexelCopyBufferLayout { offset: 0, bytes_per_row: Some(256 * 4), rows_per_image: None }, + wgpu::Extent3d { width: 256, height: 1, depth_or_array_layers: 1 }, + ); + self.palette_dirty = false; + } + let (w, h) = self.framebuffer_size; self.queue.write_texture( wgpu::TexelCopyTextureInfoBase { texture: &self.index_tex, mip_level: 0, origin: wgpu::Origin3d::ZERO, aspect: wgpu::TextureAspect::All },