15 个版本

0.4.5 2024年6月24日
0.4.3 2024年5月19日
0.4.1 2024年1月11日
0.4.0 2023年11月14日
0.1.0 2022年1月20日

#5 in GUI

Download history 16164/week @ 2024-05-04 15837/week @ 2024-05-11 16838/week @ 2024-05-18 18519/week @ 2024-05-25 16592/week @ 2024-06-01 30222/week @ 2024-06-08 31146/week @ 2024-06-15 34110/week @ 2024-06-22 25697/week @ 2024-06-29 21892/week @ 2024-07-06 23176/week @ 2024-07-13 24014/week @ 2024-07-20 25136/week @ 2024-07-27 25530/week @ 2024-08-03 27683/week @ 2024-08-10 22646/week @ 2024-08-17

105,001 每月下载量
128 个包(31 个直接使用) 中使用

MIT/Apache

150KB
3K SLoC

概述

正如库 minifb 的流行所显示,将 2D 缓冲区/图像以平台无关的方式放置在窗口中是有用的。然而,minifb 自己处理窗口管理的方法存在代码重复的问题。Rust 生态系统(如 winit)中已经有了非常高质量的库,而 minifb 的窗口管理实现并不理想。例如,它在某些平台上偶尔会发生段错误,并且缺少设置窗口图标等关键功能。虽然可以向 minifb 添加这些功能,但使用标准的窗口处理系统更有意义。

Softbuffer 集成了 raw-window-handle 包,允许以跨平台的方式向窗口写入,同时使用 Rust 生态系统中可用的非常高质量的专用窗口管理库。

关于 pixels 呢?Pixels 与 Softbuffer 实现了非常相似的目标,但存在两个关键区别。Pixels 提供了对显示内容的 GPU 加速后处理的容量,而 Softbuffer 则没有。由于没有这种后处理,Softbuffer 不依赖于 GPU 或硬件加速的图形堆栈,因此更适合在没有硬件加速的安装环境中使用(例如 VM、旧电脑、配置错误的驱动程序的电脑)。当不需要 GPU 加速的后处理效果时,应使用 Softbuffer 而不是 pixels。

许可证 & 致谢

本库采用 MIT 或 Apache-2.0 许可证双授权,与 minifb 和 rust 相同。代码中有很大一部分来自 minifb 库,用于执行特定平台的工作。

平台支持

Softbuffer 支持部分但在 raw-window-handle 中并非所有平台。欢迎提交拉取请求添加新平台!不过,所有 winit 在桌面使用的桌面主要平台都得到了支持。

目前,新平台的支持优先级是

  1. 在每个操作系统上至少有一个平台能够工作(例如 Win32 或 WinRT 中的一个,或者 Xlib、Xcb 和 Wayland 中的一个),并且
  2. 每个操作系统上的这个平台应该是 winit 使用的平台。

(即使它不符合上述优先级,也会接受任何平台的拉取请求。)

平台
Android NDK
AppKit
Orbital
UIKit
Wayland
Web
Win32
WinRT
XCB
Xlib

✅: 存在
❔: 不成熟
❌: 不存在

WebAssembly

要运行使用 Web 后端的示例: cargo run-wasm --example winit

示例

use std::num::NonZeroU32;
use std::rc::Rc;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::Window;

include!("../examples/utils/winit_app.rs");

fn main() {
    let event_loop = EventLoop::new().unwrap();

    let mut app = winit_app::WinitAppBuilder::with_init(|elwt| {
        let window = {
            let window = elwt.create_window(Window::default_attributes());
            Rc::new(window.unwrap())
        };
        let context = softbuffer::Context::new(window.clone()).unwrap();
        let surface = softbuffer::Surface::new(&context, window.clone()).unwrap();

        (window, surface)
    }).with_event_handler(|state, event, elwt| {
        let (window, surface) = state;
        elwt.set_control_flow(ControlFlow::Wait);

        match event {
            Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
                let (width, height) = {
                    let size = window.inner_size();
                    (size.width, size.height)
                };
                surface
                    .resize(
                        NonZeroU32::new(width).unwrap(),
                        NonZeroU32::new(height).unwrap(),
                    )
                    .unwrap();

                let mut buffer = surface.buffer_mut().unwrap();
                for index in 0..(width * height) {
                    let y = index / width;
                    let x = index % width;
                    let red = x % 255;
                    let green = y % 255;
                    let blue = (x * y) % 255;

                    buffer[index as usize] = blue | (green << 8) | (red << 16);
                }

                buffer.present().unwrap();
            }
            Event::WindowEvent {
                event: WindowEvent::CloseRequested,
                window_id,
            } if window_id == window.id() => {
                elwt.exit();
            }
            _ => {}
        }
    });

    event_loop.run_app(&mut app).unwrap();
}

变更日志

请参阅 变更日志,了解此包的各个版本及其每个版本中的更改。

依赖项

~0.1–18MB
~212K SLoC