diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index 7b93372..ec4d169 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -401,6 +401,33 @@ impl Session { pub fn backend_type(&self) -> BackendType { self.0.device.backend_type() } + + #[cfg(target_os = "macos")] + pub unsafe fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: &::metal::CommandBufferRef) -> CmdBuf { + let cmd_buf = Some(self.0.device.cmd_buf_from_raw_mtl(raw_cmd_buf)); + let resources = Vec::new(); + // Expect client to do cleanup manually. + let session = Weak::new(); + CmdBuf { + cmd_buf, + fence: None, + resources, + session, + } + } + + #[cfg(target_os = "macos")] + pub unsafe fn image_from_raw_mtl( + &self, + raw_texture: &::metal::TextureRef, + width: u32, + height: u32, + ) -> Image { + let image = self.0.device.image_from_raw_mtl(raw_texture, width, height); + // Expect client to do cleanup manually. + let session = Weak::new(); + Image(Arc::new(ImageInner { image, session })) + } } impl SessionInner { diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index be0c1d6..3ee72b2 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -16,8 +16,8 @@ mod macros; mod mux; pub use crate::mux::{ - DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, - Swapchain, + DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, + Surface, Swapchain, }; pub use bufwrite::BufWrite; pub use hub::{ diff --git a/piet-gpu-hal/src/metal.rs b/piet-gpu-hal/src/metal.rs index dd622fc..00eef49 100644 --- a/piet-gpu-hal/src/metal.rs +++ b/piet-gpu-hal/src/metal.rs @@ -216,6 +216,20 @@ impl MtlDevice { helpers, } } + + pub fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: metal::CommandBuffer) -> CmdBuf { + let cmd_buf = raw_cmd_buf; + let helpers = self.helpers.clone(); + CmdBuf { cmd_buf, helpers } + } + + pub fn image_from_raw_mtl(&self, texture: metal::Texture, width: u32, height: u32) -> Image { + Image { + texture, + width, + height, + } + } } impl crate::backend::Device for MtlDevice { diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 654a77b..e4d7937 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -209,8 +209,35 @@ impl Instance { // missing functionality). impl Device { #[cfg(target_os = "macos")] - pub fn new_from_raw_mtl(device: &::metal::DeviceRef, queue: &::metal::CommandQueueRef) -> Device { - Device::Mtl(metal::MtlDevice::new_from_raw_mtl(device.to_owned(), queue.to_owned())) + pub fn new_from_raw_mtl( + device: &::metal::DeviceRef, + queue: &::metal::CommandQueueRef, + ) -> Device { + Device::Mtl(metal::MtlDevice::new_from_raw_mtl( + device.to_owned(), + queue.to_owned(), + )) + } + + #[cfg(target_os = "macos")] + pub fn cmd_buf_from_raw_mtl(&self, raw_cmd_buf: &::metal::CommandBufferRef) -> CmdBuf { + // Note: this will cause problems if we support multiple back-ends on mac. But it will + // be a compile error; + let Device::Mtl(d) = self; + CmdBuf::Mtl(d.cmd_buf_from_raw_mtl(raw_cmd_buf.to_owned())) + } + + #[cfg(target_os = "macos")] + pub fn image_from_raw_mtl( + &self, + raw_texture: &::metal::TextureRef, + width: u32, + height: u32, + ) -> Image { + // Note: this will cause problems if we support multiple back-ends on mac. But it will + // be a compile error; + let Device::Mtl(d) = self; + Image::Mtl(d.image_from_raw_mtl(raw_texture.to_owned(), width, height)) } pub fn query_gpu_info(&self) -> GpuInfo { diff --git a/piet-gpu/src/glyph_render.rs b/piet-gpu/src/glyph_render.rs new file mode 100644 index 0000000..900938d --- /dev/null +++ b/piet-gpu/src/glyph_render.rs @@ -0,0 +1,63 @@ +// Copyright 2022 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +//! An experimental API for glyph rendering. + +use swash::{scale::ScaleContext, CacheKey, FontRef}; + +use crate::{encoder::GlyphEncoder, PietGpuRenderContext}; + +pub struct GlyphRenderer { + pub render_ctx: PietGpuRenderContext, + scale_context: ScaleContext, +} + +#[repr(transparent)] +pub struct FontId(CacheKey); + +impl GlyphRenderer { + pub fn new() -> GlyphRenderer { + GlyphRenderer { + render_ctx: PietGpuRenderContext::new(), + scale_context: ScaleContext::new(), + } + } + + pub unsafe fn add_glyph(&mut self, font_data: &[u8], font_id: u64, glyph_id: u16) { + // This transmute is dodgy because the definition in swash isn't repr(transparent). + // I think the best solution is to have a from_u64 method, but we'll work that out + // later. + let font_id = FontId(std::mem::transmute(font_id)); + let encoder = self.make_glyph(font_data, font_id, glyph_id); + self.render_ctx.encode_glyph(&encoder); + // TODO: don't fill glyph if RGBA + self.render_ctx.fill_glyph(0xff_ff_ff_ff); + } + + fn make_glyph(&mut self, font_data: &[u8], font_id: FontId, glyph_id: u16) -> GlyphEncoder { + let mut encoder = GlyphEncoder::default(); + let font_ref = FontRef { + data: font_data, + offset: 0, + key: font_id.0, + }; + let mut scaler = self.scale_context.builder(font_ref).size(2048.).build(); + if let Some(outline) = scaler.scale_outline(glyph_id) { + crate::text::append_outline(&mut encoder, outline.verbs(), outline.points()); + } + encoder + } +} diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index f045d65..47de115 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -1,4 +1,5 @@ mod encoder; +pub mod glyph_render; mod gradient; mod pico_svg; mod render_ctx; diff --git a/piet-gpu/src/text.rs b/piet-gpu/src/text.rs index dec3ffa..0fb508b 100644 --- a/piet-gpu/src/text.rs +++ b/piet-gpu/src/text.rs @@ -260,7 +260,7 @@ impl TextLayoutBuilder for PietGpuTextLayoutBuilder { } } -fn append_outline(encoder: &mut GlyphEncoder, verbs: &[Verb], points: &[Vector]) { +pub(crate) fn append_outline(encoder: &mut GlyphEncoder, verbs: &[Verb], points: &[Vector]) { let mut path_encoder = encoder.path_encoder(); let mut i = 0; for verb in verbs {