mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 13:03:02 +03:00
Start on metal rendering infrastructure
This commit is contained in:
parent
d14c943150
commit
292b41ad57
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -336,7 +336,7 @@ dependencies = [
|
||||
"cocoa-foundation",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
@ -351,7 +351,7 @@ dependencies = [
|
||||
"block",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
@ -396,7 +396,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -408,7 +408,7 @@ checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -420,7 +420,7 @@ checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
|
||||
dependencies = [
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -616,28 +616,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared 0.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||
dependencies = [
|
||||
"foreign-types-macros",
|
||||
"foreign-types-shared 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-macros"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63f713f8b2aa9e24fec85b0e290c56caee12e3b6ae0aeeda238a75b28251afd6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -646,12 +625,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684cf33bb7f28497939e8c7cf17e3e4e3b8d9a0080ffa4f8ae2f515442ee855"
|
||||
|
||||
[[package]]
|
||||
name = "freetype"
|
||||
version = "0.7.0"
|
||||
@ -773,7 +746,7 @@ dependencies = [
|
||||
"core-text",
|
||||
"ctor",
|
||||
"font-kit",
|
||||
"foreign-types 0.5.0",
|
||||
"foreign-types",
|
||||
"log",
|
||||
"metal",
|
||||
"num_cpus",
|
||||
@ -924,7 +897,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"foreign-types 0.3.2",
|
||||
"foreign-types",
|
||||
"log",
|
||||
"objc",
|
||||
]
|
||||
|
@ -29,7 +29,7 @@ core-foundation = "0.9"
|
||||
core-graphics = "0.22.2"
|
||||
core-text = "19.2"
|
||||
font-kit = {git = "https://github.com/zed-industries/font-kit", rev = "8eaf7a918eafa28b0a37dc759e2e0e7683fa24f1"}
|
||||
foreign-types = "0.5"
|
||||
foreign-types = "0.3"
|
||||
log = "0.4"
|
||||
metal = "0.21"
|
||||
metal = "0.21.0"
|
||||
objc = "0.2"
|
||||
|
@ -1,8 +1,14 @@
|
||||
use std::{env, path::PathBuf};
|
||||
use std::{
|
||||
env,
|
||||
path::PathBuf,
|
||||
process::{self, Command},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
generate_dispatch_bindings();
|
||||
compile_context_predicate_parser();
|
||||
compile_metal_shaders();
|
||||
generate_shader_bindings();
|
||||
}
|
||||
|
||||
fn generate_dispatch_bindings() {
|
||||
@ -20,7 +26,7 @@ fn generate_dispatch_bindings() {
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("dispatch_sys.rs"))
|
||||
.expect("couldn't write bindings");
|
||||
.expect("couldn't write dispatch bindings");
|
||||
}
|
||||
|
||||
fn compile_context_predicate_parser() {
|
||||
@ -33,3 +39,60 @@ fn compile_context_predicate_parser() {
|
||||
.file(parser_c)
|
||||
.compile("tree_sitter_context_predicate");
|
||||
}
|
||||
|
||||
const SHADER_HEADER_PATH: &'static str = "./src/platform/mac/shaders/shaders.h";
|
||||
|
||||
fn compile_metal_shaders() {
|
||||
let shader_path = "./src/platform/mac/shaders/shaders.metal";
|
||||
let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air");
|
||||
let metallib_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.metallib");
|
||||
|
||||
println!("cargo:rerun-if-changed={}", SHADER_HEADER_PATH);
|
||||
println!("cargo:rerun-if-changed={}", shader_path);
|
||||
|
||||
let output = Command::new("xcrun")
|
||||
.args(&["-sdk", "macosx", "metal", "-c", shader_path, "-o"])
|
||||
.arg(&air_output_path)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
if !output.status.success() {
|
||||
eprintln!(
|
||||
"metal shader compilation failed:\n{}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let output = Command::new("xcrun")
|
||||
.args(&["-sdk", "macosx", "metallib"])
|
||||
.arg(air_output_path)
|
||||
.arg("-o")
|
||||
.arg(metallib_output_path)
|
||||
.output()
|
||||
.unwrap();
|
||||
|
||||
if !output.status.success() {
|
||||
eprintln!(
|
||||
"metallib compilation failed:\n{}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_shader_bindings() {
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header(SHADER_HEADER_PATH)
|
||||
.whitelist_type("GPUIQuadInputIndex")
|
||||
.whitelist_type("GPUIQuad")
|
||||
.whitelist_type("GPUIQuadUniforms")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
.generate()
|
||||
.expect("unable to generate bindings");
|
||||
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("shaders.rs"))
|
||||
.expect("couldn't write shader bindings");
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ mod app;
|
||||
mod dispatcher;
|
||||
mod event;
|
||||
mod geometry;
|
||||
mod renderer;
|
||||
mod runner;
|
||||
mod window;
|
||||
|
||||
|
63
gpui/src/platform/mac/renderer.rs
Normal file
63
gpui/src/platform/mac/renderer.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use crate::Scene;
|
||||
|
||||
use super::window::RenderContext;
|
||||
|
||||
const SHADERS_METALLIB: &'static [u8] =
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
|
||||
|
||||
pub struct Renderer {
|
||||
quad_pipeline_state: metal::RenderPipelineState,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new(device: &metal::DeviceRef, pixel_format: metal::MTLPixelFormat) -> Result<Self> {
|
||||
let library = device
|
||||
.new_library_with_data(SHADERS_METALLIB)
|
||||
.map_err(|message| anyhow!("error building metal library: {}", message))?;
|
||||
|
||||
Ok(Self {
|
||||
quad_pipeline_state: build_pipeline_state(
|
||||
device,
|
||||
&library,
|
||||
"quad",
|
||||
"quad_vertex",
|
||||
"quad_fragment",
|
||||
pixel_format,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render(&mut self, scene: &Scene, ctx: RenderContext) {}
|
||||
}
|
||||
|
||||
fn build_pipeline_state(
|
||||
device: &metal::DeviceRef,
|
||||
library: &metal::LibraryRef,
|
||||
label: &str,
|
||||
vertex_fn_name: &str,
|
||||
fragment_fn_name: &str,
|
||||
pixel_format: metal::MTLPixelFormat,
|
||||
) -> Result<metal::RenderPipelineState> {
|
||||
let vertex_fn = library
|
||||
.get_function(vertex_fn_name, None)
|
||||
.map_err(|message| anyhow!("error locating vertex function: {}", message))?;
|
||||
let fragment_fn = library
|
||||
.get_function(fragment_fn_name, None)
|
||||
.map_err(|message| anyhow!("error locating fragment function: {}", message))?;
|
||||
|
||||
let mut descriptor = metal::RenderPipelineDescriptor::new();
|
||||
descriptor.set_label(label);
|
||||
descriptor.set_vertex_function(Some(vertex_fn.as_ref()));
|
||||
descriptor.set_fragment_function(Some(fragment_fn.as_ref()));
|
||||
descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_pixel_format(pixel_format);
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&descriptor)
|
||||
.map_err(|message| anyhow!("could not create render pipeline state: {}", message))
|
||||
}
|
17
gpui/src/platform/mac/shaders/shaders.h
Normal file
17
gpui/src/platform/mac/shaders/shaders.h
Normal file
@ -0,0 +1,17 @@
|
||||
#include <simd/simd.h>
|
||||
|
||||
typedef enum {
|
||||
GPUIQuadInputIndexVertices = 0,
|
||||
GPUIQuadInputIndexQuads = 1,
|
||||
GPUIQuadInputIndexUniforms = 2,
|
||||
} GPUIQuadInputIndex;
|
||||
|
||||
typedef struct {
|
||||
vector_float2 origin;
|
||||
vector_float2 size;
|
||||
vector_float4 background_color;
|
||||
} GPUIQuad;
|
||||
|
||||
typedef struct {
|
||||
vector_float2 viewport_size;
|
||||
} GPUIQuadUniforms;
|
30
gpui/src/platform/mac/shaders/shaders.metal
Normal file
30
gpui/src/platform/mac/shaders/shaders.metal
Normal file
@ -0,0 +1,30 @@
|
||||
#include <metal_stdlib>
|
||||
#include "shaders.h"
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct QuadFragmentInput {
|
||||
float4 position [[position]];
|
||||
GPUIQuad quad;
|
||||
};
|
||||
|
||||
vertex QuadFragmentInput quad_vertex(
|
||||
uint unit_vertex_id [[vertex_id]],
|
||||
uint quad_id [[instance_id]],
|
||||
constant float2 *unit_vertices [[buffer(GPUIQuadInputIndexVertices)]],
|
||||
constant GPUIQuad *quads [[buffer(GPUIQuadInputIndexQuads)]],
|
||||
constant GPUIQuadUniforms *uniforms [[buffer(GPUIQuadInputIndexUniforms)]]
|
||||
) {
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
GPUIQuad quad = quads[quad_id];
|
||||
float4 position = float4((unit_vertex * quad.size + quad.origin) / (uniforms->viewport_size / 2.0), 0.0, 1.0);
|
||||
|
||||
return QuadFragmentInput {
|
||||
position,
|
||||
quad,
|
||||
};
|
||||
}
|
||||
|
||||
fragment float4 quad_fragment(QuadFragmentInput input [[stage_in]]) {
|
||||
return input.quad.background_color;
|
||||
}
|
@ -12,13 +12,16 @@ use cocoa::{
|
||||
},
|
||||
base::{id, nil},
|
||||
foundation::{NSAutoreleasePool, NSSize, NSString},
|
||||
quartzcore::AutoresizingMask,
|
||||
};
|
||||
use ctor::ctor;
|
||||
use foreign_types::ForeignType as _;
|
||||
use metal::{MTLClearColor, MTLLoadAction, MTLStoreAction};
|
||||
use objc::{
|
||||
class,
|
||||
declare::ClassDecl,
|
||||
msg_send,
|
||||
runtime::{Class, Object, Sel, BOOL, NO, YES},
|
||||
runtime::{Class, Object, Protocol, Sel, BOOL, NO, YES},
|
||||
sel, sel_impl,
|
||||
};
|
||||
use pathfinder_geometry::vector::vec2f;
|
||||
@ -31,13 +34,12 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use super::geometry::RectFExt;
|
||||
use super::{geometry::RectFExt, renderer::Renderer};
|
||||
|
||||
const WINDOW_STATE_IVAR: &'static str = "windowState";
|
||||
|
||||
static mut WINDOW_CLASS: *const Class = ptr::null();
|
||||
static mut VIEW_CLASS: *const Class = ptr::null();
|
||||
static mut DELEGATE_CLASS: *const Class = ptr::null();
|
||||
|
||||
#[ctor]
|
||||
unsafe fn build_classes() {
|
||||
@ -63,7 +65,9 @@ unsafe fn build_classes() {
|
||||
VIEW_CLASS = {
|
||||
let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();
|
||||
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
|
||||
|
||||
decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));
|
||||
|
||||
decl.add_method(
|
||||
sel!(keyDown:),
|
||||
handle_view_event as extern "C" fn(&Object, Sel, id),
|
||||
@ -84,20 +88,25 @@ unsafe fn build_classes() {
|
||||
sel!(scrollWheel:),
|
||||
handle_view_event as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
decl.register()
|
||||
};
|
||||
|
||||
DELEGATE_CLASS = {
|
||||
let mut decl = ClassDecl::new("GPUIWindowDelegate", class!(NSObject)).unwrap();
|
||||
decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());
|
||||
decl.add_method(
|
||||
sel!(dealloc),
|
||||
dealloc_delegate as extern "C" fn(&Object, Sel),
|
||||
sel!(makeBackingLayer),
|
||||
make_backing_layer as extern "C" fn(&Object, Sel) -> id,
|
||||
);
|
||||
decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);
|
||||
decl.add_method(
|
||||
sel!(windowDidResize:),
|
||||
window_did_resize as extern "C" fn(&Object, Sel, id),
|
||||
sel!(viewDidChangeBackingProperties),
|
||||
view_did_change_backing_properties as extern "C" fn(&Object, Sel),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(setFrameSize:),
|
||||
set_frame_size as extern "C" fn(&Object, Sel, NSSize),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(displayLayer:),
|
||||
display_layer as extern "C" fn(&Object, Sel, id),
|
||||
);
|
||||
|
||||
decl.register()
|
||||
};
|
||||
}
|
||||
@ -110,6 +119,17 @@ struct WindowState {
|
||||
resize_callback: RefCell<Option<Box<dyn FnMut(Vector2F, f32)>>>,
|
||||
synthetic_drag_counter: Cell<usize>,
|
||||
executor: Rc<executor::Foreground>,
|
||||
scene_to_render: RefCell<Option<Scene>>,
|
||||
renderer: RefCell<Renderer>,
|
||||
command_queue: metal::CommandQueue,
|
||||
device: metal::Device,
|
||||
layer: id,
|
||||
}
|
||||
|
||||
pub struct RenderContext<'a> {
|
||||
pub drawable_size: Vector2F,
|
||||
pub device: &'a metal::Device,
|
||||
pub command_encoder: &'a metal::RenderCommandEncoderRef,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
@ -117,6 +137,8 @@ impl Window {
|
||||
options: platform::WindowOptions,
|
||||
executor: Rc<executor::Foreground>,
|
||||
) -> Result<Self> {
|
||||
const PIXEL_FORMAT: metal::MTLPixelFormat = metal::MTLPixelFormat::BGRA8Unorm;
|
||||
|
||||
unsafe {
|
||||
let pool = NSAutoreleasePool::new(nil);
|
||||
|
||||
@ -138,12 +160,20 @@ impl Window {
|
||||
return Err(anyhow!("window returned nil from initializer"));
|
||||
}
|
||||
|
||||
let delegate: id = msg_send![DELEGATE_CLASS, alloc];
|
||||
let delegate = delegate.init();
|
||||
if native_window == nil {
|
||||
return Err(anyhow!("delegate returned nil from initializer"));
|
||||
}
|
||||
native_window.setDelegate_(delegate);
|
||||
let device = metal::Device::system_default()
|
||||
.ok_or_else(|| anyhow!("could not find default metal device"))?;
|
||||
|
||||
let layer: id = msg_send![class!(CAMetalLayer), layer];
|
||||
let _: () = msg_send![layer, setDevice: device.as_ptr()];
|
||||
let _: () = msg_send![layer, setPixelFormat: PIXEL_FORMAT];
|
||||
let _: () = msg_send![layer, setAllowsNextDrawableTimeout: NO];
|
||||
let _: () = msg_send![layer, setNeedsDisplayOnBoundsChange: YES];
|
||||
let _: () = msg_send![layer, setPresentsWithTransaction: YES];
|
||||
let _: () = msg_send![
|
||||
layer,
|
||||
setAutoresizingMask: AutoresizingMask::WIDTH_SIZABLE
|
||||
| AutoresizingMask::HEIGHT_SIZABLE
|
||||
];
|
||||
|
||||
let native_view: id = msg_send![VIEW_CLASS, alloc];
|
||||
let native_view = NSView::init(native_view);
|
||||
@ -157,6 +187,11 @@ impl Window {
|
||||
resize_callback: RefCell::new(None),
|
||||
synthetic_drag_counter: Cell::new(0),
|
||||
executor,
|
||||
scene_to_render: Default::default(),
|
||||
renderer: RefCell::new(Renderer::new(&device, PIXEL_FORMAT)?),
|
||||
command_queue: device.new_command_queue(),
|
||||
device,
|
||||
layer,
|
||||
}));
|
||||
|
||||
(*native_window).set_ivar(
|
||||
@ -167,10 +202,6 @@ impl Window {
|
||||
WINDOW_STATE_IVAR,
|
||||
Rc::into_raw(window.0.clone()) as *const c_void,
|
||||
);
|
||||
(*delegate).set_ivar(
|
||||
WINDOW_STATE_IVAR,
|
||||
Rc::into_raw(window.0.clone()) as *const c_void,
|
||||
);
|
||||
|
||||
if let Some(title) = options.title.as_ref() {
|
||||
native_window.setTitle_(NSString::alloc(nil).init_str(title));
|
||||
@ -237,7 +268,10 @@ impl platform::Window for Window {
|
||||
}
|
||||
|
||||
fn render_scene(&self, scene: Scene) {
|
||||
log::info!("render scene");
|
||||
*self.0.scene_to_render.borrow_mut() = Some(scene);
|
||||
unsafe {
|
||||
let _: () = msg_send![self.0.native_window.contentView(), setNeedsDisplay: YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,14 +327,6 @@ extern "C" fn dealloc_view(this: &Object, _: Sel) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn dealloc_delegate(this: &Object, _: Sel) {
|
||||
unsafe {
|
||||
let raw: *mut c_void = *this.get_ivar(WINDOW_STATE_IVAR);
|
||||
Rc::from_raw(raw as *mut WindowState);
|
||||
let () = msg_send![super(this, class!(NSObject)), dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||
let window = unsafe { window_state(this) };
|
||||
|
||||
@ -329,14 +355,85 @@ extern "C" fn send_event(this: &Object, _: Sel, native_event: id) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||
extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id {
|
||||
let window = unsafe { window_state(this) };
|
||||
let size = window.size();
|
||||
let scale_factor = window.scale_factor();
|
||||
if let Some(callback) = window.resize_callback.borrow_mut().as_mut() {
|
||||
callback(size, scale_factor);
|
||||
window.layer
|
||||
}
|
||||
|
||||
extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) {
|
||||
let window;
|
||||
unsafe {
|
||||
window = window_state(this);
|
||||
let _: () = msg_send![window.layer, setContentsScale: window.scale_factor() as f64];
|
||||
}
|
||||
|
||||
if let Some(callback) = window.resize_callback.borrow_mut().as_mut() {
|
||||
let size = window.size();
|
||||
let scale_factor = window.scale_factor();
|
||||
callback(size, scale_factor);
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
||||
let window;
|
||||
unsafe {
|
||||
window = window_state(this);
|
||||
if window.size() == vec2f(size.width as f32, size.height as f32) {
|
||||
return;
|
||||
}
|
||||
|
||||
let _: () = msg_send![super(this, class!(NSView)), setFrameSize: size];
|
||||
|
||||
let scale_factor = window.scale_factor() as f64;
|
||||
let drawable_size: NSSize = NSSize {
|
||||
width: size.width * scale_factor,
|
||||
height: size.height * scale_factor,
|
||||
};
|
||||
let _: () = msg_send![window.layer, setDrawableSize: drawable_size];
|
||||
}
|
||||
|
||||
if let Some(callback) = window.resize_callback.borrow_mut().as_mut() {
|
||||
let size = window.size();
|
||||
let scale_factor = window.scale_factor();
|
||||
callback(size, scale_factor);
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let window = window_state(this);
|
||||
|
||||
if let Some(scene) = window.scene_to_render.borrow_mut().take() {
|
||||
let drawable: &metal::MetalDrawableRef = msg_send![window.layer, nextDrawable];
|
||||
|
||||
let render_pass_descriptor = metal::RenderPassDescriptor::new();
|
||||
let color_attachment = render_pass_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap();
|
||||
color_attachment.set_texture(Some(drawable.texture()));
|
||||
color_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
color_attachment.set_store_action(MTLStoreAction::Store);
|
||||
color_attachment.set_clear_color(MTLClearColor::new(0., 0., 0., 1.));
|
||||
|
||||
let command_buffer = window.command_queue.new_command_buffer();
|
||||
let command_encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
|
||||
|
||||
window.renderer.borrow_mut().render(
|
||||
&scene,
|
||||
RenderContext {
|
||||
drawable_size: window.size() * window.scale_factor(),
|
||||
device: &window.device,
|
||||
command_encoder,
|
||||
},
|
||||
);
|
||||
|
||||
command_encoder.end_encoding();
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
drawable.present();
|
||||
};
|
||||
}
|
||||
drop(window);
|
||||
}
|
||||
|
||||
fn schedule_synthetic_drag(window_state: &Rc<WindowState>, position: Vector2F) {
|
||||
|
Loading…
Reference in New Issue
Block a user