Checkpoint
This commit is contained in:
@@ -28,6 +28,10 @@ impl<Key> MetalAtlas<Key> {
|
||||
tiles_by_key: Default::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn texture(&self, id: AtlasTextureId) -> metal::Texture {
|
||||
self.0.lock().textures[id.0 as usize].metal_texture.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct MetalAtlasState<Key> {
|
||||
@@ -123,10 +127,10 @@ impl MetalAtlasTexture {
|
||||
bounds: allocation.rectangle.into(),
|
||||
};
|
||||
let region = metal::MTLRegion::new_2d(
|
||||
u32::from(tile.bounds.origin.x) as u64,
|
||||
u32::from(tile.bounds.origin.y) as u64,
|
||||
u32::from(tile.bounds.size.width) as u64,
|
||||
u32::from(tile.bounds.size.height) as u64,
|
||||
tile.bounds.origin.x.into(),
|
||||
tile.bounds.origin.y.into(),
|
||||
tile.bounds.size.width.into(),
|
||||
tile.bounds.size.height.into(),
|
||||
);
|
||||
self.metal_texture.replace_region(
|
||||
region,
|
||||
@@ -149,15 +153,15 @@ impl MetalAtlasTexture {
|
||||
|
||||
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)
|
||||
etagere::Size::new(size.width.into(), size.width.into())
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
x: DevicePixels::from(value.x),
|
||||
y: DevicePixels::from(value.y),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,8 +169,8 @@ impl From<etagere::Point> for Point<DevicePixels> {
|
||||
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),
|
||||
width: DevicePixels::from(size.width),
|
||||
height: DevicePixels::from(size.height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
point, size, AtlasTextureId, DevicePixels, MetalAtlas, MonochromeSprite, Quad,
|
||||
RasterizedGlyphId, Scene, Size,
|
||||
RasterizeGlyphParams, Scene, Size,
|
||||
};
|
||||
use cocoa::{
|
||||
base::{NO, YES},
|
||||
@@ -18,10 +18,11 @@ pub struct MetalRenderer {
|
||||
device: metal::Device,
|
||||
layer: metal::MetalLayer,
|
||||
command_queue: CommandQueue,
|
||||
quad_pipeline_state: metal::RenderPipelineState,
|
||||
quads_pipeline_state: metal::RenderPipelineState,
|
||||
sprites_pipeline_state: metal::RenderPipelineState,
|
||||
unit_vertices: metal::Buffer,
|
||||
instances: metal::Buffer,
|
||||
glyph_atlas: Arc<MetalAtlas<RasterizedGlyphId>>,
|
||||
glyph_atlas: Arc<MetalAtlas<RasterizeGlyphParams>>,
|
||||
}
|
||||
|
||||
impl MetalRenderer {
|
||||
@@ -81,15 +82,24 @@ impl MetalRenderer {
|
||||
MTLResourceOptions::StorageModeManaged,
|
||||
);
|
||||
|
||||
let quad_pipeline_state = build_pipeline_state(
|
||||
let quads_pipeline_state = build_pipeline_state(
|
||||
&device,
|
||||
&library,
|
||||
"quad",
|
||||
"quads",
|
||||
"quad_vertex",
|
||||
"quad_fragment",
|
||||
PIXEL_FORMAT,
|
||||
);
|
||||
|
||||
let sprites_pipeline_state = build_pipeline_state(
|
||||
&device,
|
||||
&library,
|
||||
"sprites",
|
||||
"monochrome_sprite_vertex",
|
||||
"monochrome_sprite_fragment",
|
||||
PIXEL_FORMAT,
|
||||
);
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
let glyph_atlas = Arc::new(MetalAtlas::new(
|
||||
Size {
|
||||
@@ -104,7 +114,8 @@ impl MetalRenderer {
|
||||
device,
|
||||
layer,
|
||||
command_queue,
|
||||
quad_pipeline_state,
|
||||
quads_pipeline_state,
|
||||
sprites_pipeline_state,
|
||||
unit_vertices,
|
||||
instances,
|
||||
glyph_atlas,
|
||||
@@ -115,7 +126,7 @@ impl MetalRenderer {
|
||||
&*self.layer
|
||||
}
|
||||
|
||||
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizedGlyphId>> {
|
||||
pub fn glyph_atlas(&self) -> &Arc<MetalAtlas<RasterizeGlyphParams>> {
|
||||
&self.glyph_atlas
|
||||
}
|
||||
|
||||
@@ -123,8 +134,8 @@ impl MetalRenderer {
|
||||
let layer = self.layer.clone();
|
||||
let viewport_size = layer.drawable_size();
|
||||
let viewport_size: Size<DevicePixels> = size(
|
||||
(viewport_size.width.ceil() as u32).into(),
|
||||
(viewport_size.height.ceil() as u32).into(),
|
||||
(viewport_size.width.ceil() as i32).into(),
|
||||
(viewport_size.height.ceil() as i32).into(),
|
||||
);
|
||||
let drawable = if let Some(drawable) = layer.next_drawable() {
|
||||
drawable
|
||||
@@ -144,8 +155,8 @@ impl MetalRenderer {
|
||||
depth_texture_desc.set_pixel_format(metal::MTLPixelFormat::Depth32Float);
|
||||
depth_texture_desc.set_storage_mode(metal::MTLStorageMode::Private);
|
||||
depth_texture_desc.set_usage(metal::MTLTextureUsage::RenderTarget);
|
||||
depth_texture_desc.set_width(u32::from(viewport_size.width) as u64);
|
||||
depth_texture_desc.set_height(u32::from(viewport_size.height) as u64);
|
||||
depth_texture_desc.set_width(i32::from(viewport_size.width) as u64);
|
||||
depth_texture_desc.set_height(i32::from(viewport_size.height) as u64);
|
||||
let depth_texture = self.device.new_texture(&depth_texture_desc);
|
||||
let depth_attachment = render_pass_descriptor.depth_attachment().unwrap();
|
||||
|
||||
@@ -168,8 +179,8 @@ impl MetalRenderer {
|
||||
command_encoder.set_viewport(metal::MTLViewport {
|
||||
originX: 0.0,
|
||||
originY: 0.0,
|
||||
width: u32::from(viewport_size.width) as f64,
|
||||
height: u32::from(viewport_size.height) as f64,
|
||||
width: i32::from(viewport_size.width) as f64,
|
||||
height: i32::from(viewport_size.height) as f64,
|
||||
znear: 0.0,
|
||||
zfar: 1.0,
|
||||
});
|
||||
@@ -226,7 +237,7 @@ impl MetalRenderer {
|
||||
}
|
||||
align_offset(offset);
|
||||
|
||||
command_encoder.set_render_pipeline_state(&self.quad_pipeline_state);
|
||||
command_encoder.set_render_pipeline_state(&self.quads_pipeline_state);
|
||||
command_encoder.set_vertex_buffer(
|
||||
QuadInputIndex::Vertices as u64,
|
||||
Some(&self.unit_vertices),
|
||||
@@ -273,12 +284,77 @@ impl MetalRenderer {
|
||||
fn draw_monochrome_sprites(
|
||||
&mut self,
|
||||
texture_id: AtlasTextureId,
|
||||
monochrome: &[MonochromeSprite],
|
||||
sprites: &[MonochromeSprite],
|
||||
offset: &mut usize,
|
||||
viewport_size: Size<DevicePixels>,
|
||||
command_encoder: &metal::RenderCommandEncoderRef,
|
||||
) {
|
||||
// todo!()
|
||||
// dbg!(sprites);
|
||||
|
||||
if sprites.is_empty() {
|
||||
return;
|
||||
}
|
||||
align_offset(offset);
|
||||
|
||||
let texture = self.glyph_atlas.texture(texture_id);
|
||||
let texture_size = size(
|
||||
DevicePixels(texture.width() as i32),
|
||||
DevicePixels(texture.height() as i32),
|
||||
);
|
||||
command_encoder.set_render_pipeline_state(&self.sprites_pipeline_state);
|
||||
command_encoder.set_vertex_buffer(
|
||||
MonochromeSpriteInputIndex::Vertices as u64,
|
||||
Some(&self.unit_vertices),
|
||||
0,
|
||||
);
|
||||
command_encoder.set_vertex_buffer(
|
||||
MonochromeSpriteInputIndex::Sprites as u64,
|
||||
Some(&self.instances),
|
||||
*offset as u64,
|
||||
);
|
||||
command_encoder.set_vertex_bytes(
|
||||
MonochromeSpriteInputIndex::ViewportSize as u64,
|
||||
mem::size_of_val(&viewport_size) as u64,
|
||||
&viewport_size as *const Size<DevicePixels> as *const _,
|
||||
);
|
||||
command_encoder.set_vertex_bytes(
|
||||
MonochromeSpriteInputIndex::AtlasTextureSize as u64,
|
||||
mem::size_of_val(&texture_size) as u64,
|
||||
&texture_size as *const Size<DevicePixels> as *const _,
|
||||
);
|
||||
command_encoder.set_fragment_buffer(
|
||||
MonochromeSpriteInputIndex::Sprites as u64,
|
||||
Some(&self.instances),
|
||||
*offset as u64,
|
||||
);
|
||||
command_encoder.set_fragment_texture(
|
||||
MonochromeSpriteInputIndex::AtlasTexture as u64,
|
||||
Some(&texture),
|
||||
);
|
||||
|
||||
let sprite_bytes_len = mem::size_of::<MonochromeSprite>() * sprites.len();
|
||||
let buffer_contents = unsafe { (self.instances.contents() as *mut u8).add(*offset) };
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
sprites.as_ptr() as *const u8,
|
||||
buffer_contents,
|
||||
sprite_bytes_len,
|
||||
);
|
||||
}
|
||||
|
||||
let next_offset = *offset + sprite_bytes_len;
|
||||
assert!(
|
||||
next_offset <= INSTANCE_BUFFER_SIZE,
|
||||
"instance buffer exhausted"
|
||||
);
|
||||
|
||||
command_encoder.draw_primitives_instanced(
|
||||
metal::MTLPrimitiveType::Triangle,
|
||||
0,
|
||||
6,
|
||||
sprites.len() as u64,
|
||||
);
|
||||
*offset = next_offset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +410,6 @@ enum MonochromeSpriteInputIndex {
|
||||
Vertices = 0,
|
||||
Sprites = 1,
|
||||
ViewportSize = 2,
|
||||
AtlasSize = 3,
|
||||
AtlasTextureSize = 3,
|
||||
AtlasTexture = 4,
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
|
||||
constant Size_DevicePixels *viewport_size
|
||||
[[buffer(MonochromeSpriteInputIndex_ViewportSize)]],
|
||||
constant Size_DevicePixels *atlas_size
|
||||
[[buffer(MonochromeSpriteInputIndex_AtlasSize)]]) {
|
||||
[[buffer(MonochromeSpriteInputIndex_AtlasTextureSize)]]) {
|
||||
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
MonochromeSprite sprite = sprites[sprite_id];
|
||||
@@ -149,11 +149,13 @@ fragment float4 monochrome_sprite_fragment(
|
||||
MonochromeSpriteVertexOutput input [[stage_in]],
|
||||
constant MonochromeSprite *sprites
|
||||
[[buffer(MonochromeSpriteInputIndex_Sprites)]],
|
||||
texture2d<float> atlas
|
||||
texture2d<float> atlas_texture
|
||||
[[texture(MonochromeSpriteInputIndex_AtlasTexture)]]) {
|
||||
MonochromeSprite sprite = sprites[input.sprite_id];
|
||||
constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
|
||||
float4 sample = atlas.sample(atlas_sampler, input.tile_position);
|
||||
constexpr sampler atlas_texture_sampler(mag_filter::linear,
|
||||
min_filter::linear);
|
||||
float4 sample =
|
||||
atlas_texture.sample(atlas_texture_sampler, input.tile_position);
|
||||
float clip_distance =
|
||||
quad_sdf(input.position.xy, sprite.clip_bounds, sprite.clip_corner_radii);
|
||||
float4 color = input.color;
|
||||
@@ -256,52 +258,3 @@ float quad_sdf(float2 point, Bounds_Pixels bounds,
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
// struct SpriteFragmentInput {
|
||||
// float4 position [[position]];
|
||||
// float2 atlas_position;
|
||||
// float4 color [[flat]];
|
||||
// uchar compute_winding [[flat]];
|
||||
// };
|
||||
|
||||
// vertex SpriteFragmentInput sprite_vertex(
|
||||
// uint unit_vertex_id [[vertex_id]],
|
||||
// uint sprite_id [[instance_id]],
|
||||
// constant float2 *unit_vertices
|
||||
// [[buffer(GPUISpriteVertexInputIndexVertices)]], constant GPUISprite
|
||||
// *sprites [[buffer(GPUISpriteVertexInputIndexSprites)]], constant float2
|
||||
// *viewport_size [[buffer(GPUISpriteVertexInputIndexViewportSize)]],
|
||||
// constant float2 *atlas_size
|
||||
// [[buffer(GPUISpriteVertexInputIndexAtlasSize)]]
|
||||
// ) {
|
||||
// float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
// GPUISprite sprite = sprites[sprite_id];
|
||||
// float2 position = unit_vertex * sprite.target_size + sprite.origin;
|
||||
// float4 device_position = to_device_position(position, *viewport_size);
|
||||
// float2 atlas_position = (unit_vertex * sprite.source_size +
|
||||
// sprite.atlas_origin) / *atlas_size;
|
||||
|
||||
// return SpriteFragmentInput {
|
||||
// device_position,
|
||||
// atlas_position,
|
||||
// coloru_to_colorf(sprite.color),
|
||||
// sprite.compute_winding
|
||||
// };
|
||||
// }
|
||||
|
||||
// fragment float4 sprite_fragment(
|
||||
// SpriteFragmentInput input [[stage_in]],
|
||||
// texture2d<float> atlas [[ texture(GPUISpriteFragmentInputIndexAtlas) ]]
|
||||
// ) {
|
||||
// constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
|
||||
// float4 color = input.color;
|
||||
// float4 sample = atlas.sample(atlas_sampler, input.atlas_position);
|
||||
// float mask;
|
||||
// if (input.compute_winding) {
|
||||
// mask = 1. - abs(1. - fmod(sample.r, 2.));
|
||||
// } else {
|
||||
// mask = sample.a;
|
||||
// }
|
||||
// color.a *= mask;
|
||||
// return color;
|
||||
// }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
point, px, size, Bounds, DevicePixels, Font, FontFeatures, FontId, FontMetrics, FontStyle,
|
||||
FontWeight, GlyphId, Pixels, PlatformTextSystem, Point, RasterizedGlyphId, Result, ShapedGlyph,
|
||||
ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
||||
FontWeight, GlyphId, Pixels, PlatformTextSystem, Point, RasterizeGlyphParams, Result,
|
||||
ShapedGlyph, ShapedLine, ShapedRun, SharedString, Size, SUBPIXEL_VARIANTS,
|
||||
};
|
||||
use anyhow::anyhow;
|
||||
use cocoa::appkit::{CGFloat, CGPoint};
|
||||
@@ -136,8 +136,8 @@ impl PlatformTextSystem for MacTextSystem {
|
||||
|
||||
fn rasterize_glyph(
|
||||
&self,
|
||||
glyph_id: &RasterizedGlyphId,
|
||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)> {
|
||||
glyph_id: &RasterizeGlyphParams,
|
||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||
self.0.read().rasterize_glyph(glyph_id)
|
||||
}
|
||||
|
||||
@@ -232,8 +232,8 @@ impl MacTextSystemState {
|
||||
|
||||
fn rasterize_glyph(
|
||||
&self,
|
||||
glyph_id: &RasterizedGlyphId,
|
||||
) -> Result<(Bounds<DevicePixels>, Vec<u8>)> {
|
||||
glyph_id: &RasterizeGlyphParams,
|
||||
) -> Result<(Size<DevicePixels>, Vec<u8>)> {
|
||||
let font = &self.fonts[glyph_id.font_id.0];
|
||||
let scale = Transform2F::from_scale(glyph_id.scale_factor);
|
||||
let glyph_bounds = font.raster_bounds(
|
||||
@@ -252,18 +252,15 @@ impl MacTextSystemState {
|
||||
glyph_id.subpixel_variant.x.min(1) as i32,
|
||||
glyph_id.subpixel_variant.y.min(1) as i32,
|
||||
);
|
||||
let cx_bounds = RectI::new(
|
||||
glyph_bounds.origin(),
|
||||
glyph_bounds.size() + subpixel_padding,
|
||||
);
|
||||
let bitmap_size = glyph_bounds.size() + subpixel_padding;
|
||||
|
||||
let mut bytes = vec![0; cx_bounds.width() as usize * cx_bounds.height() as usize];
|
||||
let mut bytes = vec![0; bitmap_size.x() as usize * bitmap_size.y() as usize];
|
||||
let cx = CGContext::create_bitmap_context(
|
||||
Some(bytes.as_mut_ptr() as *mut _),
|
||||
cx_bounds.width() as usize,
|
||||
cx_bounds.height() as usize,
|
||||
bitmap_size.x() as usize,
|
||||
bitmap_size.y() as usize,
|
||||
8,
|
||||
cx_bounds.width() as usize,
|
||||
bitmap_size.x() as usize,
|
||||
&CGColorSpace::create_device_gray(),
|
||||
kCGImageAlphaOnly,
|
||||
);
|
||||
@@ -298,7 +295,7 @@ impl MacTextSystemState {
|
||||
cx,
|
||||
);
|
||||
|
||||
Ok((cx_bounds.into(), bytes))
|
||||
Ok((bitmap_size.into(), bytes))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,14 +508,23 @@ impl From<RectF> for Bounds<f32> {
|
||||
impl From<RectI> for Bounds<DevicePixels> {
|
||||
fn from(rect: RectI) -> Self {
|
||||
Bounds {
|
||||
origin: point(
|
||||
DevicePixels(rect.origin_x() as u32),
|
||||
DevicePixels(rect.origin_y() as u32),
|
||||
),
|
||||
size: size(
|
||||
DevicePixels(rect.width() as u32),
|
||||
DevicePixels(rect.height() as u32),
|
||||
),
|
||||
origin: point(DevicePixels(rect.origin_x()), DevicePixels(rect.origin_y())),
|
||||
size: size(DevicePixels(rect.width()), DevicePixels(rect.height())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vector2I> for Size<DevicePixels> {
|
||||
fn from(value: Vector2I) -> Self {
|
||||
size(value.x().into(), value.y().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RectI> for Bounds<i32> {
|
||||
fn from(rect: RectI) -> Self {
|
||||
Bounds {
|
||||
origin: point(rect.origin_x(), rect.origin_y()),
|
||||
size: size(rect.width(), rect.height()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ use crate::{
|
||||
point, px, size, AnyWindowHandle, Bounds, Event, KeyDownEvent, Keystroke, MacScreen, Modifiers,
|
||||
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMovedEvent, MouseUpEvent, NSRectExt,
|
||||
Pixels, Platform, PlatformAtlas, PlatformDispatcher, PlatformInputHandler, PlatformScreen,
|
||||
PlatformWindow, Point, RasterizedGlyphId, Scene, Size, Timer, WindowAppearance, WindowBounds,
|
||||
WindowKind, WindowOptions, WindowPromptLevel,
|
||||
PlatformWindow, Point, RasterizeGlyphParams, Scene, Size, Timer, WindowAppearance,
|
||||
WindowBounds, WindowKind, WindowOptions, WindowPromptLevel,
|
||||
};
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::{
|
||||
@@ -886,7 +886,7 @@ impl PlatformWindow for MacWindow {
|
||||
}
|
||||
}
|
||||
|
||||
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<RasterizedGlyphId>> {
|
||||
fn glyph_atlas(&self) -> Arc<dyn PlatformAtlas<RasterizeGlyphParams>> {
|
||||
self.0.lock().renderer.glyph_atlas().clone()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user