mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 19:08:00 +03:00
Checkpoint
This commit is contained in:
parent
dcaf4c905f
commit
12ba10bc2c
@ -32,7 +32,7 @@ pub struct Text<S> {
|
||||
|
||||
impl<S: 'static> Element for Text<S> {
|
||||
type State = S;
|
||||
type FrameState = Arc<Mutex<Option<TextLayout>>>;
|
||||
type FrameState = Arc<Mutex<Option<TextFrameState>>>;
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
@ -54,7 +54,6 @@ impl<S: 'static> Element for Text<S> {
|
||||
let layout_id = cx.request_measured_layout(Default::default(), rem_size, {
|
||||
let frame_state = paint_state.clone();
|
||||
move |_, _| {
|
||||
dbg!("starting measurement");
|
||||
let Some(line_layout) = text_system
|
||||
.layout_line(
|
||||
text.as_ref(),
|
||||
@ -65,23 +64,21 @@ impl<S: 'static> Element for Text<S> {
|
||||
else {
|
||||
return Size::default();
|
||||
};
|
||||
dbg!("bbbb");
|
||||
|
||||
let size = Size {
|
||||
width: line_layout.width(),
|
||||
height: line_height,
|
||||
};
|
||||
|
||||
frame_state.lock().replace(TextLayout {
|
||||
frame_state.lock().replace(TextFrameState {
|
||||
line: Arc::new(line_layout),
|
||||
line_height,
|
||||
});
|
||||
|
||||
dbg!(size)
|
||||
size
|
||||
}
|
||||
});
|
||||
|
||||
dbg!("got to end of text layout");
|
||||
Ok((layout_id?, paint_state))
|
||||
}
|
||||
|
||||
@ -89,22 +86,20 @@ impl<S: 'static> Element for Text<S> {
|
||||
&mut self,
|
||||
layout: Layout,
|
||||
_: &mut Self::State,
|
||||
paint_state: &mut Self::FrameState,
|
||||
frame_state: &mut Self::FrameState,
|
||||
cx: &mut ViewContext<S>,
|
||||
) -> Result<()> {
|
||||
let line;
|
||||
let line_height;
|
||||
{
|
||||
let paint_state = paint_state.lock();
|
||||
let paint_state = paint_state
|
||||
let frame_state = frame_state.lock();
|
||||
let frame_state = frame_state
|
||||
.as_ref()
|
||||
.expect("measurement has not been performed");
|
||||
line = paint_state.line.clone();
|
||||
line_height = paint_state.line_height;
|
||||
line = frame_state.line.clone();
|
||||
line_height = frame_state.line_height;
|
||||
}
|
||||
|
||||
let _text_style = cx.text_style();
|
||||
|
||||
// todo!("We haven't added visible bounds to the new element system yet, so this is a placeholder.");
|
||||
let visible_bounds = layout.bounds;
|
||||
line.paint(&layout, visible_bounds, line_height, cx)?;
|
||||
@ -113,7 +108,7 @@ impl<S: 'static> Element for Text<S> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TextLayout {
|
||||
pub struct TextFrameState {
|
||||
line: Arc<Line>,
|
||||
line_height: Pixels,
|
||||
}
|
||||
|
@ -180,14 +180,30 @@ pub trait PlatformTextSystem: Send + Sync {
|
||||
) -> Vec<usize>;
|
||||
}
|
||||
|
||||
pub trait PlatformSpriteSystem<Key> {
|
||||
pub trait PlatformAtlas<Key> {
|
||||
fn get_or_insert_with(
|
||||
&self,
|
||||
key: Key,
|
||||
build: impl FnOnce() -> (Size<DevicePixels>, Vec<u8>),
|
||||
) -> MonochromeSprite;
|
||||
) -> AtlasTile;
|
||||
|
||||
fn clear(&self);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct AtlasTile {
|
||||
pub(crate) texture_id: AtlasTextureId,
|
||||
pub(crate) tile_id: TileId,
|
||||
pub(crate) bounds_in_atlas: Bounds<DevicePixels>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct AtlasTextureId(pub(crate) usize);
|
||||
|
||||
pub(crate) type TileId = etagere::AllocId;
|
||||
|
||||
pub trait PlatformInputHandler {
|
||||
fn selected_text_range(&self) -> Option<Range<usize>>;
|
||||
fn marked_text_range(&self) -> Option<Range<usize>>;
|
||||
|
@ -2,11 +2,11 @@
|
||||
///! an origin at the bottom left of the main display.
|
||||
mod dispatcher;
|
||||
mod events;
|
||||
mod metal_atlas;
|
||||
mod metal_renderer;
|
||||
mod open_type;
|
||||
mod platform;
|
||||
mod screen;
|
||||
mod sprite;
|
||||
mod text_system;
|
||||
mod window;
|
||||
mod window_appearence;
|
||||
@ -31,9 +31,9 @@ use std::{
|
||||
};
|
||||
|
||||
pub use dispatcher::*;
|
||||
pub use metal_atlas::*;
|
||||
pub use platform::*;
|
||||
pub use screen::*;
|
||||
pub use sprite::*;
|
||||
pub use text_system::*;
|
||||
pub use window::*;
|
||||
|
||||
|
164
crates/gpui3/src/platform/mac/metal_atlas.rs
Normal file
164
crates/gpui3/src/platform/mac/metal_atlas.rs
Normal file
@ -0,0 +1,164 @@
|
||||
use crate::{AtlasTextureId, AtlasTile, Bounds, DevicePixels, PlatformAtlas, Point, Size};
|
||||
use collections::HashMap;
|
||||
use etagere::BucketedAtlasAllocator;
|
||||
use foreign_types::ForeignType;
|
||||
use metal::{Device, TextureDescriptor, TextureDescriptorRef};
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||
use std::hash::Hash;
|
||||
|
||||
pub struct MetalAtlas<Key>(RwLock<MetalAtlasState<Key>>);
|
||||
|
||||
struct MetalAtlasState<Key> {
|
||||
device: Device,
|
||||
texture_descriptor: TextureDescriptor,
|
||||
textures: Vec<MetalAtlasTexture>,
|
||||
tiles_by_key: HashMap<Key, AtlasTile>,
|
||||
}
|
||||
|
||||
impl<Key> PlatformAtlas<Key> for MetalAtlas<Key>
|
||||
where
|
||||
Key: Eq + Hash,
|
||||
{
|
||||
fn get_or_insert_with(
|
||||
&self,
|
||||
key: Key,
|
||||
build: impl FnOnce() -> (Size<DevicePixels>, Vec<u8>),
|
||||
) -> AtlasTile {
|
||||
let lock = self.0.upgradable_read();
|
||||
if let Some(tile) = lock.tiles_by_key.get(&key) {
|
||||
return tile.clone();
|
||||
} else {
|
||||
let mut lock = RwLockUpgradableReadGuard::upgrade(lock);
|
||||
let (size, bytes) = build();
|
||||
lock.textures
|
||||
.iter_mut()
|
||||
.rev()
|
||||
.find_map(|texture| texture.allocate(size, &bytes))
|
||||
.unwrap_or_else(|| {
|
||||
let texture = lock.push_texture(size);
|
||||
texture
|
||||
.allocate(size, &bytes)
|
||||
.expect("could not allocate a tile in new texture")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn clear(&self) {
|
||||
self.0.write().tiles_by_key.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl<Key> MetalAtlasState<Key> {
|
||||
fn push_texture(&mut self, min_size: Size<DevicePixels>) -> &mut MetalAtlasTexture {
|
||||
let default_atlas_size = Size {
|
||||
width: self.texture_descriptor.width().into(),
|
||||
height: self.texture_descriptor.height().into(),
|
||||
};
|
||||
let size;
|
||||
let metal_texture;
|
||||
|
||||
if min_size.width > default_atlas_size.width || min_size.height > default_atlas_size.height
|
||||
{
|
||||
let descriptor = unsafe {
|
||||
let descriptor_ptr: *mut metal::MTLTextureDescriptor =
|
||||
msg_send![self.texture_descriptor, copy];
|
||||
metal::TextureDescriptor::from_ptr(descriptor_ptr)
|
||||
};
|
||||
descriptor.set_width(min_size.width.into());
|
||||
descriptor.set_height(min_size.height.into());
|
||||
|
||||
size = min_size;
|
||||
metal_texture = self.device.new_texture(&descriptor);
|
||||
} else {
|
||||
size = default_atlas_size;
|
||||
metal_texture = self.device.new_texture(&self.texture_descriptor);
|
||||
}
|
||||
|
||||
let atlas_texture = MetalAtlasTexture {
|
||||
id: AtlasTextureId(self.textures.len()),
|
||||
allocator: etagere::BucketedAtlasAllocator::new(size.into()),
|
||||
metal_texture,
|
||||
};
|
||||
self.textures.push(atlas_texture);
|
||||
self.textures.last_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct MetalAtlasTexture {
|
||||
id: AtlasTextureId,
|
||||
allocator: BucketedAtlasAllocator,
|
||||
metal_texture: metal::Texture,
|
||||
}
|
||||
|
||||
impl MetalAtlasTexture {
|
||||
fn allocate(&mut self, size: Size<DevicePixels>, bytes: &[u8]) -> Option<AtlasTile> {
|
||||
let size = size.into();
|
||||
let allocation = self.allocator.allocate(size)?;
|
||||
let tile = AtlasTile {
|
||||
texture_id: self.id,
|
||||
tile_id: allocation.id,
|
||||
bounds_in_atlas: allocation.rectangle.into(),
|
||||
};
|
||||
let region = metal::MTLRegion::new_2d(
|
||||
u32::from(tile.bounds_in_atlas.origin.x) as u64,
|
||||
u32::from(tile.bounds_in_atlas.origin.y) as u64,
|
||||
u32::from(tile.bounds_in_atlas.size.width) as u64,
|
||||
u32::from(tile.bounds_in_atlas.size.height) as u64,
|
||||
);
|
||||
self.metal_texture.replace_region(
|
||||
region,
|
||||
0,
|
||||
bytes.as_ptr() as *const _,
|
||||
u32::from(
|
||||
tile.bounds_in_atlas
|
||||
.size
|
||||
.width
|
||||
.to_bytes(self.bytes_per_pixel()),
|
||||
) as u64,
|
||||
);
|
||||
Some(tile)
|
||||
}
|
||||
|
||||
fn bytes_per_pixel(&self) -> u8 {
|
||||
use metal::MTLPixelFormat::*;
|
||||
match self.metal_texture.pixel_format() {
|
||||
A8Unorm | R8Unorm => 1,
|
||||
RGBA8Unorm | BGRA8Unorm => 4,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Size<DevicePixels>> for etagere::Size {
|
||||
fn from(size: Size<DevicePixels>) -> Self {
|
||||
etagere::Size::new(u32::from(size.width) as i32, u32::from(size.width) as i32)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Point> for Point<DevicePixels> {
|
||||
fn from(value: etagere::Point) -> Self {
|
||||
Point {
|
||||
x: DevicePixels::from(value.x as u32),
|
||||
y: DevicePixels::from(value.y as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Size> for Size<DevicePixels> {
|
||||
fn from(size: etagere::Size) -> Self {
|
||||
Size {
|
||||
width: DevicePixels::from(size.width as u32),
|
||||
height: DevicePixels::from(size.height as u32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<etagere::Rectangle> for Bounds<DevicePixels> {
|
||||
fn from(rectangle: etagere::Rectangle) -> Self {
|
||||
Bounds {
|
||||
origin: rectangle.min.into(),
|
||||
size: rectangle.size().into(),
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{iter::Peekable, mem};
|
||||
|
||||
use super::{Bounds, Hsla, Pixels, Point};
|
||||
use crate::{Corners, DevicePixels, Edges};
|
||||
use crate::{AtlasTile, Corners, DevicePixels, Edges};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
// Exported to metal
|
||||
@ -243,10 +243,8 @@ impl From<Quad> for Primitive {
|
||||
pub struct MonochromeSprite {
|
||||
pub order: u32,
|
||||
pub bounds: Bounds<Pixels>,
|
||||
pub atlas_id: AtlasId,
|
||||
pub tile_id: TileId,
|
||||
pub bounds_in_atlas: Bounds<DevicePixels>,
|
||||
pub color: Option<Hsla>,
|
||||
pub color: Hsla,
|
||||
pub tile: AtlasTile,
|
||||
}
|
||||
|
||||
impl MonochromeSprite {
|
||||
|
Loading…
Reference in New Issue
Block a user