use valo_dl::{BlendMode, DisplayList, Filter, Image, MipmapMode, Paint, Sampling, TileMode};
use valo_geometry::Color;
use valo_renderer::{ImageDesc, MemoryReport, RenderStats, RenderTarget, RendererCore};
pub struct Context {
renderer: RendererCore,
queue: wgpu::Queue,
}
impl Context {
pub fn new(device: wgpu::Device, queue: wgpu::Queue) -> Self {
Self {
renderer: RendererCore::new(device, queue.clone()),
queue,
}
}
pub fn memory_report(&self) -> MemoryReport {
self.renderer.memory_report()
}
pub fn render(&mut self, dl: &DisplayList, target: &RenderTarget) -> RenderStats {
self.renderer.render(dl, target)
}
pub fn set_hide_missing_glyphs(&mut self, hide: bool) {
self.renderer.set_hide_missing_glyphs(hide);
}
pub fn set_text_tiers(&mut self, tiers: valo_renderer::TextTiers) {
self.renderer.set_text_tiers(tiers);
}
pub fn set_text_raster_hold(&mut self, held: bool) {
self.renderer.set_text_raster_hold(held);
}
pub fn set_raster_hold(&mut self, held: bool) {
self.renderer.set_raster_hold(held);
}
pub fn device(&self) -> &wgpu::Device {
self.renderer.device()
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn queue_handle(&self) -> wgpu::Queue {
self.queue.clone()
}
pub fn present(&self, frame: crate::SurfaceFrame) {
frame.present(&self.queue);
}
pub fn upload_image(&mut self, desc: ImageDesc, pixels: &[u8]) -> Image {
self.renderer.images().upload(desc, pixels)
}
pub fn import_image(&mut self, texture: wgpu::Texture, size: [u32; 2]) -> Image {
self.renderer.images().finish_external(texture, size, 1)
}
#[cfg(target_arch = "wasm32")]
pub fn upload_image_bitmap(&mut self, bitmap: &web_sys::ImageBitmap, mips: bool) -> Image {
let size = [bitmap.width(), bitmap.height()];
self.upload_external_image(
wgpu::ExternalImageSource::ImageBitmap(bitmap.clone()),
size,
mips,
)
}
#[cfg(target_arch = "wasm32")]
pub fn upload_external_image(
&mut self,
source: wgpu::ExternalImageSource,
size: [u32; 2],
mips: bool,
) -> Image {
self.upload_external_image_region(source, [0, 0], size, mips)
}
#[cfg(target_arch = "wasm32")]
pub fn upload_external_image_region(
&mut self,
source: wgpu::ExternalImageSource,
origin: [u32; 2],
size: [u32; 2],
mips: bool,
) -> Image {
let mip_levels = if mips {
32 - size[0].max(size[1]).max(1).leading_zeros()
} else {
1
};
let texture = self
.renderer
.images()
.create_image_texture(size, mip_levels);
copy_external_image(&self.queue, source, origin, &texture, size);
self.renderer
.images()
.finish_external(texture, size, mip_levels)
}
#[cfg(target_arch = "wasm32")]
pub fn refresh_external_image(
&mut self,
image: &Image,
source: wgpu::ExternalImageSource,
size: [u32; 2],
) -> bool {
if image.size() != size {
return false;
}
copy_external_image(&self.queue, source, [0, 0], image.texture(), size);
self.renderer.images().regenerate_mips(image);
true
}
}
#[cfg(target_arch = "wasm32")]
fn copy_external_image(
queue: &wgpu::Queue,
source: wgpu::ExternalImageSource,
origin: [u32; 2],
texture: &wgpu::Texture,
size: [u32; 2],
) {
queue.copy_external_image_to_texture(
&wgpu::CopyExternalImageSourceInfo {
source,
origin: wgpu::Origin2d {
x: origin[0],
y: origin[1],
},
flip_y: false,
},
wgpu::CopyExternalImageDestInfo {
texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
color_space: wgpu::PredefinedColorSpace::Srgb,
premultiplied_alpha: true,
},
wgpu::Extent3d {
width: size[0],
height: size[1],
depth_or_array_layers: 1,
},
);
}
pub(crate) const EXACT_SAMPLING: Sampling = Sampling {
filter: Filter::Nearest,
mipmap: MipmapMode::None,
tile_x: TileMode::Clamp,
tile_y: TileMode::Clamp,
};
pub(crate) fn copy_paint() -> Paint {
Paint {
color: Color::WHITE,
blend_mode: BlendMode::Src,
..Paint::default()
}
}