mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-27 12:54:42 +00:00
Extract image rasterization into ImageCache
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
d15eda53f6
commit
bd4d73bb27
3 changed files with 58 additions and 42 deletions
|
@ -3,6 +3,7 @@ mod dispatcher;
|
|||
mod event;
|
||||
mod fonts;
|
||||
mod geometry;
|
||||
mod image_cache;
|
||||
mod platform;
|
||||
mod renderer;
|
||||
mod sprite_cache;
|
||||
|
|
49
gpui/src/platform/mac/image_cache.rs
Normal file
49
gpui/src/platform/mac/image_cache.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use metal::{MTLPixelFormat, TextureDescriptor, TextureRef};
|
||||
|
||||
use super::atlas::{AllocId, AtlasAllocator};
|
||||
use crate::{
|
||||
geometry::{rect::RectI, vector::Vector2I},
|
||||
ImageData,
|
||||
};
|
||||
use std::{collections::HashMap, mem};
|
||||
|
||||
pub struct ImageCache {
|
||||
prev_frame: HashMap<usize, (AllocId, RectI)>,
|
||||
curr_frame: HashMap<usize, (AllocId, RectI)>,
|
||||
atlases: AtlasAllocator,
|
||||
}
|
||||
|
||||
impl ImageCache {
|
||||
pub fn new(device: metal::Device, size: Vector2I) -> Self {
|
||||
let descriptor = TextureDescriptor::new();
|
||||
descriptor.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
descriptor.set_width(size.x() as u64);
|
||||
descriptor.set_height(size.y() as u64);
|
||||
Self {
|
||||
prev_frame: Default::default(),
|
||||
curr_frame: Default::default(),
|
||||
atlases: AtlasAllocator::new(device, descriptor),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, image: &ImageData) -> (AllocId, RectI) {
|
||||
let (alloc_id, atlas_bounds) = self
|
||||
.prev_frame
|
||||
.remove(&image.id)
|
||||
.or_else(|| self.curr_frame.get(&image.id).copied())
|
||||
.unwrap_or_else(|| self.atlases.upload(image.size(), image.as_bytes()));
|
||||
self.curr_frame.insert(image.id, (alloc_id, atlas_bounds));
|
||||
(alloc_id, atlas_bounds)
|
||||
}
|
||||
|
||||
pub fn finish_frame(&mut self) {
|
||||
mem::swap(&mut self.prev_frame, &mut self.curr_frame);
|
||||
for (_, (id, _)) in self.curr_frame.drain() {
|
||||
self.atlases.deallocate(id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn atlas_texture(&self, atlas_id: usize) -> Option<&TextureRef> {
|
||||
self.atlases.texture(atlas_id)
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
use super::{
|
||||
atlas::{self, AtlasAllocator},
|
||||
sprite_cache::SpriteCache,
|
||||
};
|
||||
use super::{atlas::AtlasAllocator, image_cache::ImageCache, sprite_cache::SpriteCache};
|
||||
use crate::{
|
||||
color::Color,
|
||||
geometry::{
|
||||
rect::{RectF, RectI},
|
||||
rect::RectF,
|
||||
vector::{vec2f, vec2i, Vector2F},
|
||||
},
|
||||
platform,
|
||||
|
@ -22,10 +19,8 @@ const INSTANCE_BUFFER_SIZE: usize = 1024 * 1024; // This is an arbitrary decisio
|
|||
|
||||
pub struct Renderer {
|
||||
sprite_cache: SpriteCache,
|
||||
image_cache: ImageCache,
|
||||
path_atlases: AtlasAllocator,
|
||||
image_atlases: AtlasAllocator,
|
||||
prev_rendered_images: HashMap<usize, (atlas::AllocId, RectI)>,
|
||||
curr_rendered_images: HashMap<usize, (atlas::AllocId, RectI)>,
|
||||
quad_pipeline_state: metal::RenderPipelineState,
|
||||
shadow_pipeline_state: metal::RenderPipelineState,
|
||||
sprite_pipeline_state: metal::RenderPipelineState,
|
||||
|
@ -70,10 +65,9 @@ impl Renderer {
|
|||
);
|
||||
|
||||
let sprite_cache = SpriteCache::new(device.clone(), vec2i(1024, 768), fonts);
|
||||
let image_cache = ImageCache::new(device.clone(), vec2i(1024, 768));
|
||||
let path_atlases =
|
||||
AtlasAllocator::new(device.clone(), build_path_atlas_texture_descriptor());
|
||||
let image_atlases =
|
||||
AtlasAllocator::new(device.clone(), build_image_atlas_texture_descriptor());
|
||||
let quad_pipeline_state = build_pipeline_state(
|
||||
&device,
|
||||
&library,
|
||||
|
@ -116,10 +110,8 @@ impl Renderer {
|
|||
);
|
||||
Self {
|
||||
sprite_cache,
|
||||
image_cache,
|
||||
path_atlases,
|
||||
image_atlases,
|
||||
prev_rendered_images: Default::default(),
|
||||
curr_rendered_images: Default::default(),
|
||||
quad_pipeline_state,
|
||||
shadow_pipeline_state,
|
||||
sprite_pipeline_state,
|
||||
|
@ -139,11 +131,6 @@ impl Renderer {
|
|||
) {
|
||||
let mut offset = 0;
|
||||
|
||||
mem::swap(
|
||||
&mut self.curr_rendered_images,
|
||||
&mut self.prev_rendered_images,
|
||||
);
|
||||
|
||||
let path_sprites = self.render_path_atlases(scene, &mut offset, command_buffer);
|
||||
self.render_layers(
|
||||
scene,
|
||||
|
@ -157,11 +144,7 @@ impl Renderer {
|
|||
location: 0,
|
||||
length: offset as NSUInteger,
|
||||
});
|
||||
|
||||
for (id, _) in self.prev_rendered_images.values() {
|
||||
self.image_atlases.deallocate(*id);
|
||||
}
|
||||
self.prev_rendered_images.clear();
|
||||
self.image_cache.finish_frame();
|
||||
}
|
||||
|
||||
fn render_path_atlases(
|
||||
|
@ -660,16 +643,7 @@ impl Renderer {
|
|||
let target_size = image.bounds.size() * scale_factor;
|
||||
let corner_radius = image.corner_radius * scale_factor;
|
||||
let border_width = image.border.width * scale_factor;
|
||||
let (alloc_id, atlas_bounds) = self
|
||||
.prev_rendered_images
|
||||
.remove(&image.data.id)
|
||||
.or_else(|| self.curr_rendered_images.get(&image.data.id).copied())
|
||||
.unwrap_or_else(|| {
|
||||
self.image_atlases
|
||||
.upload(image.data.size(), image.data.as_bytes())
|
||||
});
|
||||
self.curr_rendered_images
|
||||
.insert(image.data.id, (alloc_id, atlas_bounds));
|
||||
let (alloc_id, atlas_bounds) = self.image_cache.render(&image.data);
|
||||
images_by_atlas
|
||||
.entry(alloc_id.atlas_id)
|
||||
.or_insert_with(Vec::new)
|
||||
|
@ -707,7 +681,7 @@ impl Renderer {
|
|||
"instance buffer exhausted"
|
||||
);
|
||||
|
||||
let texture = self.image_atlases.texture(atlas_id).unwrap();
|
||||
let texture = self.image_cache.atlas_texture(atlas_id).unwrap();
|
||||
command_encoder.set_vertex_buffer(
|
||||
shaders::GPUIImageVertexInputIndex_GPUIImageVertexInputIndexImages as u64,
|
||||
Some(&self.instances),
|
||||
|
@ -858,14 +832,6 @@ fn build_path_atlas_texture_descriptor() -> metal::TextureDescriptor {
|
|||
texture_descriptor
|
||||
}
|
||||
|
||||
fn build_image_atlas_texture_descriptor() -> metal::TextureDescriptor {
|
||||
let texture_descriptor = metal::TextureDescriptor::new();
|
||||
texture_descriptor.set_width(2048);
|
||||
texture_descriptor.set_height(2048);
|
||||
texture_descriptor.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
texture_descriptor
|
||||
}
|
||||
|
||||
fn align_offset(offset: &mut usize) {
|
||||
let r = *offset % 256;
|
||||
if r > 0 {
|
||||
|
|
Loading…
Reference in a new issue