mvdocs

# ImageDisplay 实现与生命周期

# 线程与绘制

UI 线程管理来源、交互、双精度视口及覆盖层快照。后台工作线程按当前物理缩放建立需要的灰度降采样层级, 1:1 或放大时只保留原始层;缩小时按需补充并复用已生成的层级。新层完成前保持上一次有效画面, 不在渲染线程生成层级或上传不适合当前缩放的整幅原图。层级可继续缩小到 1×1, 不能在达到 512 瓦片边长时提前终止;16384×4000 在 1/256 倍时选择第 8 级。 后台任务持有快照引用,并在切帧前完成。 CompositionCustomVisualHandler 在渲染线程接收不可变状态,通过 Skia lease 绘制,不在 render 回调中读取控件属性。

图像层使用 512×512 瓦片。缩小时按物理缩放选择二倍降采样层级,放大使用原始层和最近邻。 仅创建可见瓦片,平移时保留预算内的旧瓦片并优先淘汰非可见项。新帧替换时清空上一帧瓦片; 来源和帧身份由独立快照隔离,不能把同一坐标的旧瓦片用于新图。

原图左上角为 (0,0),像素边界为整数,中心为 (x+0.5,y+0.5)。 图像坐标到 DIP 的比例为 Zoom / RenderScaling;像素查询始终读取原始层。 网格只绘制可见整数边界,线宽一物理像素并在设备坐标中对齐。

绘制顺序为图像、像素格、图像坐标覆盖层、屏幕坐标覆盖层。公开覆盖层使用 ImmediateDrawingContext,不交出 Skia lease 或 GPU 资源。快照必须不可变并能在渲染线程安全使用。

# 帧与背压

FrameImageSource 在 Shared 定义来源和租约,不引用 Skia 或 MachineVision。 每次提交只接受一个帧,生产者等待其绘制确认;显示控件保留当前帧,并最多准备一个新帧。 首版不允许并发提交,来源也不缓存历史帧。

挂载时连接消费会话,换源和卸载时取消该会话。停止、取消或错误不能伪造 FrameRendered。 取消已被消费的帧仅取消等待,底层内存仍由安全持有的快照释放。

冻结与不可见状态停止消费;冻结时仍可缩放、平移和重绘已保留的当前帧。帧完成准备后、安装前再次检查可呈现状态;真正完成 Skia 绘制和覆盖层绘制后, 才完成该帧的确认任务。无 Skia 后端或绘制失败通过错误状态及提交异常暴露。

# 内存与销毁

原始缓冲区、降采样数组、CPU 瓦片副本及转换暂存经过字节预算。实时输入在转移所有权前预留其 owner 容量, 包括内存池返回的额外容量。单帧接收上限为 CPU 预算的三分之一,为当前帧、准备帧及瓦片保留空间。

静态文件复用应用 loader,无显示控件私有下载或文件缓存;加载期间的解码也受应用 loader 的资源限制。 显示控件通过受信任包内部的按请求 codec 接口选择 Gray8 解码,来源读取、内容校验和调度仍在统一 loader 内完成。 灰度 PNG 直接解码到 Gray8 owner;彩色栅格需要转换时先预留 RGBA 暂存,再转换并归还暂存预算。 codec 使用独立解码身份并关闭结果缓存,避免把某个显示控件的帧租约共享给另一个消费者。 应用 loader 的编码读取与在途缓存仍属于应用图片服务,不计为控件持有的独立缓存。

GPU 瓦片按每像素四字节保守计量,预算只覆盖控件持有的纹理,不宣称限制驱动或 Avalonia 的全局图形内存。 CPU/GPU 公开读数直接读取原子预算账本,瓦片释放后即更新,不等待下一次绘制回报。 账本属于控件实例,跨卸载与重挂载复用,仍被旧渲染状态持有的数据继续计量;预算上限仅允许在首次挂载前配置。 图形 context 更换时丢弃瓦片,从 CPU 原图重建;软件后端沿用同一坐标和瓦片路径。

UI 当前帧和渲染状态分别持有快照引用。换源先取消生产与准备,再归还 UI 引用; render handler 处理替换或卸载消息后归还渲染引用。最后一个引用销毁时释放帧 owner 和预算。

# 验证入口

从源码仓库运行定向契约验证,不运行全量回归:

dotnet test tests/Avanti.Toolkit.Controls.Shared.Tests/Avanti.Toolkit.Controls.Shared.Tests.csproj --framework net10.0 --filter FullyQualifiedName~FrameImageSourceTests
dotnet test tests/Avanti.Toolkit.Desktop.Controls.Tests/Avanti.Toolkit.Desktop.Controls.Tests.csproj --framework net10.0 --filter FullyQualifiedName~ImageDisplayContractTests

从项目根目录执行 bun tasks.ts gallery run,Gallery 直接引用本控件源码,不需要构建或同步 NuGet 包。