Expose a C API for getting pathfinder to render to an EGL surface
This commit is contained in:
parent
29ef8b57e0
commit
9fd479d604
|
@ -30,12 +30,19 @@ const char* QUAD_NAMES[NUM_QUADS] = {
|
||||||
"quad6",
|
"quad6",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* SVG_NAMES[NUM_QUADS] = {
|
||||||
|
"svg/nba-notext.svg",
|
||||||
|
"svg/paper.svg",
|
||||||
|
"svg/Ghostscript_Tiger.svg",
|
||||||
|
"svg/julius-caesar-with-bg.svg",
|
||||||
|
"svg/julius-caesar.svg",
|
||||||
|
"svg/pathfinder_logo.svg",
|
||||||
|
};
|
||||||
|
|
||||||
PathfinderDemo::PathfinderDemo() {
|
PathfinderDemo::PathfinderDemo() {
|
||||||
ML_LOG(Debug, "PathfinderDemo Constructor.");
|
ML_LOG(Debug, "PathfinderDemo Constructor.");
|
||||||
|
|
||||||
// Place your constructor implementation here.
|
// Place your constructor implementation here.
|
||||||
svg_filecount_ = magicleap_pathfinder_svg_filecount();
|
|
||||||
svg_filenames_ = magicleap_pathfinder_svg_filenames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PathfinderDemo::~PathfinderDemo() {
|
PathfinderDemo::~PathfinderDemo() {
|
||||||
|
@ -113,12 +120,23 @@ int PathfinderDemo::init() {
|
||||||
// Initialize pathfinder
|
// Initialize pathfinder
|
||||||
if (!pathfinder_) {
|
if (!pathfinder_) {
|
||||||
ML_LOG(Info, "Pathfinder initializing");
|
ML_LOG(Info, "Pathfinder initializing");
|
||||||
pathfinder_ = magicleap_pathfinder_init(dpy, surf);
|
pathfinder_ = magicleap_pathfinder_init();
|
||||||
ML_LOG(Info, "Pathfinder initialized");
|
ML_LOG(Info, "Pathfinder initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t width = plane->getWidth();
|
||||||
|
uint32_t height = plane->getHeight();
|
||||||
|
|
||||||
// Render the SVG
|
// Render the SVG
|
||||||
magicleap_pathfinder_render(pathfinder_, dpy, surf, svg_filenames_[i % svg_filecount_]);
|
MagicLeapPathfinderRenderOptions options = {
|
||||||
|
dpy,
|
||||||
|
surf,
|
||||||
|
{ 0.5, 0.5, 0.5, 1.0 },
|
||||||
|
{ 0, 0, width, height },
|
||||||
|
SVG_NAMES[i],
|
||||||
|
};
|
||||||
|
|
||||||
|
magicleap_pathfinder_render(pathfinder_, &options);
|
||||||
eglSwapBuffers(dpy, surf);
|
eglSwapBuffers(dpy, surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,17 +220,17 @@ bool PathfinderDemo::eventListener(lumin::ServerEvent* event) {
|
||||||
|
|
||||||
bool PathfinderDemo::onClick() {
|
bool PathfinderDemo::onClick() {
|
||||||
lumin::RootNode* root_node = prism_->getRootNode();
|
lumin::RootNode* root_node = prism_->getRootNode();
|
||||||
for (int i=0; i<NUM_QUADS && i<svg_filecount_; i++) {
|
for (int i=0; i<NUM_QUADS; i++) {
|
||||||
lumin::Node* node = prism_->findNode(QUAD_NAMES[i], root_node);
|
lumin::Node* node = prism_->findNode(QUAD_NAMES[i], root_node);
|
||||||
if (node->getNodeId() == focus_node_) {
|
if (node->getNodeId() == focus_node_) {
|
||||||
dispatch(svg_filenames_[i]);
|
dispatch(SVG_NAMES[i]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathfinderDemo::dispatch(char* svg_filename) {
|
void PathfinderDemo::dispatch(const char* svg_filename) {
|
||||||
ML_LOG(Info, "Dispatching %s", svg_filename);
|
ML_LOG(Info, "Dispatching %s", svg_filename);
|
||||||
|
|
||||||
MLDispatchPacket* dispatcher;
|
MLDispatchPacket* dispatcher;
|
||||||
|
|
|
@ -91,7 +91,7 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Dispatch an SVG file to the immersive app
|
* Dispatch an SVG file to the immersive app
|
||||||
*/
|
*/
|
||||||
void dispatch(char* svg_filename);
|
void dispatch(const char* svg_filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run application login
|
* Run application login
|
||||||
|
@ -107,13 +107,17 @@ private:
|
||||||
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
|
lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders.
|
||||||
PrismSceneManager* prismSceneManager_ = nullptr;
|
PrismSceneManager* prismSceneManager_ = nullptr;
|
||||||
void* pathfinder_ = nullptr;
|
void* pathfinder_ = nullptr;
|
||||||
uint64_t svg_filecount_ = 0;
|
|
||||||
char** svg_filenames_ = nullptr;
|
|
||||||
lumin::NodeIDType focus_node_ = lumin::INVALID_NODE_ID;
|
lumin::NodeIDType focus_node_ = lumin::INVALID_NODE_ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" uint64_t magicleap_pathfinder_svg_filecount();
|
typedef struct MagicLeapPathfinderRenderOptions {
|
||||||
extern "C" char** magicleap_pathfinder_svg_filenames();
|
EGLDisplay display;
|
||||||
extern "C" void* magicleap_pathfinder_init(EGLDisplay, EGLSurface);
|
EGLSurface surface;
|
||||||
extern "C" void magicleap_pathfinder_render(void*, EGLDisplay, EGLSurface, char*);
|
float bg_color[4];
|
||||||
|
uint32_t viewport[4];
|
||||||
|
const char* svg_filename;
|
||||||
|
} MagicLeapPathfinderRenderOptions;
|
||||||
|
|
||||||
|
extern "C" void* magicleap_pathfinder_init();
|
||||||
|
extern "C" void magicleap_pathfinder_render(void*, MagicLeapPathfinderRenderOptions*);
|
||||||
extern "C" void magicleap_pathfinder_deinit(void*);
|
extern "C" void magicleap_pathfinder_deinit(void*);
|
||||||
|
|
|
@ -93,27 +93,9 @@ pub extern "C" fn magicleap_pathfinder_demo(egl_display: EGLDisplay, egl_context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SVG_FILENAMES: &[*const c_char] = &[
|
|
||||||
&b"svg/nba-notext.svg\0"[0],
|
|
||||||
&b"svg/paper.svg\0"[0],
|
|
||||||
&b"svg/Ghostscript_Tiger.svg\0"[0],
|
|
||||||
&b"svg/julius-caesar-with-bg.svg\0"[0],
|
|
||||||
&b"svg/julius-caesar.svg\0"[0],
|
|
||||||
&b"svg/pathfinder_logo.svg\0"[0],
|
|
||||||
];
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn magicleap_pathfinder_svg_filecount() -> usize {
|
|
||||||
SVG_FILENAMES.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn magicleap_pathfinder_svg_filenames() -> *const *const c_char {
|
|
||||||
&SVG_FILENAMES[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MagicLeapPathfinder {
|
struct MagicLeapPathfinder {
|
||||||
surfaces: HashMap<EGLSurface, MagicLeapPathfinderSurface>,
|
renderers: HashMap<(EGLSurface, EGLDisplay), Renderer<GLDevice>>,
|
||||||
|
svgs: HashMap<String, BuiltSVG>,
|
||||||
resources: FilesystemResourceLoader,
|
resources: FilesystemResourceLoader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,8 +108,17 @@ struct MagicLeapPathfinderSurface {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct MagicLeapPathfinderRenderOptions {
|
||||||
|
display: EGLDisplay,
|
||||||
|
surface: EGLSurface,
|
||||||
|
bg_color: [f32; 4],
|
||||||
|
viewport: [u32; 4],
|
||||||
|
svg_filename: *const c_char,
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn magicleap_pathfinder_init(dpy: EGLDisplay, surf: EGLSurface) -> *mut c_void {
|
pub extern "C" fn magicleap_pathfinder_init() -> *mut c_void {
|
||||||
unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info, &b"Pathfinder Demo\0"[0], &b"Initializing\0"[0]) };
|
unsafe { c_api::MLLoggingLog(c_api::MLLogLevel::Info, &b"Pathfinder Demo\0"[0], &b"Initializing\0"[0]) };
|
||||||
|
|
||||||
let tag = CString::new("Pathfinder Demo").unwrap();
|
let tag = CString::new("Pathfinder Demo").unwrap();
|
||||||
|
@ -145,7 +136,8 @@ pub extern "C" fn magicleap_pathfinder_init(dpy: EGLDisplay, surf: EGLSurface) -
|
||||||
info!("Initialized gl");
|
info!("Initialized gl");
|
||||||
|
|
||||||
let pf = MagicLeapPathfinder {
|
let pf = MagicLeapPathfinder {
|
||||||
surfaces: HashMap::new(),
|
renderers: HashMap::new(),
|
||||||
|
svgs: HashMap::new(),
|
||||||
resources: FilesystemResourceLoader::locate(),
|
resources: FilesystemResourceLoader::locate(),
|
||||||
};
|
};
|
||||||
info!("Initialized pf");
|
info!("Initialized pf");
|
||||||
|
@ -154,49 +146,52 @@ pub extern "C" fn magicleap_pathfinder_init(dpy: EGLDisplay, surf: EGLSurface) -
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, dpy: EGLDisplay, surf: EGLSurface, svg_filename: *const c_char) {
|
pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, options: *const MagicLeapPathfinderRenderOptions) {
|
||||||
let pf = pf as *mut MagicLeapPathfinder;
|
let pf = pf as *mut MagicLeapPathfinder;
|
||||||
if let Some(pf) = pf.as_mut() {
|
if let (Some(pf), Some(options)) = (pf.as_mut(), options.as_ref()) {
|
||||||
let resources = &pf.resources;
|
let resources = &pf.resources;
|
||||||
let pfs = pf.surfaces.entry(surf).or_insert_with(|| {
|
|
||||||
|
let svg_filename = CStr::from_ptr(options.svg_filename).to_string_lossy().into_owned();
|
||||||
|
let svg = pf.svgs.entry(svg_filename).or_insert_with(|| {
|
||||||
|
let svg_filename = CStr::from_ptr(options.svg_filename).to_string_lossy();
|
||||||
|
let data = resources.slurp(&*svg_filename).unwrap();
|
||||||
|
let tree = Tree::from_data(&data, &UsvgOptions::default()).unwrap();
|
||||||
|
BuiltSVG::from_tree(tree)
|
||||||
|
});
|
||||||
|
|
||||||
let mut width = 0;
|
let mut width = 0;
|
||||||
let mut height = 0;
|
let mut height = 0;
|
||||||
|
egl::query_surface(options.display, options.surface, egl::EGL_WIDTH, &mut width);
|
||||||
|
egl::query_surface(options.display, options.surface, egl::EGL_HEIGHT, &mut height);
|
||||||
|
let size = Point2DI32::new(width, height);
|
||||||
|
|
||||||
|
let viewport_origin = Point2DI32::new(options.viewport[0] as i32, options.viewport[1] as i32);
|
||||||
|
let viewport_size = Point2DI32::new(options.viewport[2] as i32, options.viewport[3] as i32);
|
||||||
|
let viewport = RectI32::new(viewport_origin, viewport_size);
|
||||||
|
|
||||||
|
let renderer = pf.renderers.entry((options.display, options.surface)).or_insert_with(|| {
|
||||||
let mut fbo = 0;
|
let mut fbo = 0;
|
||||||
egl::query_surface(dpy, surf, egl::EGL_WIDTH, &mut width);
|
|
||||||
egl::query_surface(dpy, surf, egl::EGL_HEIGHT, &mut height);
|
|
||||||
gl::GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fbo);
|
gl::GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fbo);
|
||||||
let device = GLDevice::new(GLVersion::GLES3, fbo as GLuint);
|
let device = GLDevice::new(GLVersion::GLES3, fbo as GLuint);
|
||||||
let size = Point2DI32::new(width, height);
|
Renderer::new(device, resources, viewport, size)
|
||||||
let viewport = RectI32::new(Point2DI32::default(), size);
|
|
||||||
let renderer = Renderer::new(device, resources, viewport, size);
|
|
||||||
let bg_color = F32x4::new(0.5, 0.5, 0.5, 1.0);
|
|
||||||
let svg_filename = CStr::from_ptr(svg_filename).to_string_lossy();
|
|
||||||
let data = resources.slurp(&*svg_filename).unwrap();
|
|
||||||
let svg = BuiltSVG::from_tree(Tree::from_data(&data, &UsvgOptions::default()).unwrap());
|
|
||||||
let mut scene = svg.scene;
|
|
||||||
scene.view_box = viewport.to_f32();
|
|
||||||
MagicLeapPathfinderSurface {
|
|
||||||
surf,
|
|
||||||
size,
|
|
||||||
viewport,
|
|
||||||
bg_color,
|
|
||||||
renderer,
|
|
||||||
scene,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
pfs.renderer.set_main_framebuffer_size(pfs.size);
|
|
||||||
pfs.renderer.set_viewport(pfs.viewport);
|
|
||||||
pfs.renderer.device.bind_default_framebuffer(pfs.viewport);
|
|
||||||
pfs.renderer.device.clear(Some(pfs.bg_color), Some(1.0), Some(0));
|
|
||||||
pfs.renderer.disable_depth();
|
|
||||||
|
|
||||||
let z_buffer = ZBuffer::new(pfs.scene.view_box);
|
let bg_color = F32x4::new(options.bg_color[0], options.bg_color[1], options.bg_color[2], options.bg_color[3]);
|
||||||
|
|
||||||
let scale = i32::min(pfs.viewport.size().x(), pfs.viewport.size().y()) as f32 /
|
svg.scene.view_box = viewport.to_f32();
|
||||||
f32::max(pfs.scene.bounds.size().x(), pfs.scene.bounds.size().y());
|
renderer.set_main_framebuffer_size(size);
|
||||||
let transform = Transform2DF32::from_translation(&pfs.scene.bounds.size().scale(-0.5))
|
renderer.set_viewport(viewport);
|
||||||
|
renderer.device.bind_default_framebuffer(viewport);
|
||||||
|
renderer.device.clear(Some(bg_color), Some(1.0), Some(0));
|
||||||
|
renderer.disable_depth();
|
||||||
|
|
||||||
|
let z_buffer = ZBuffer::new(svg.scene.view_box);
|
||||||
|
|
||||||
|
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 /
|
||||||
|
f32::max(svg.scene.bounds.size().x(), svg.scene.bounds.size().y());
|
||||||
|
let transform = Transform2DF32::from_translation(&svg.scene.bounds.size().scale(-0.5))
|
||||||
.post_mul(&Transform2DF32::from_scale(&Point2DF32::splat(scale)))
|
.post_mul(&Transform2DF32::from_scale(&Point2DF32::splat(scale)))
|
||||||
.post_mul(&Transform2DF32::from_translation(&pfs.viewport.size().to_f32().scale(0.5)));
|
.post_mul(&Transform2DF32::from_translation(&viewport_size.to_f32().scale(0.5)));
|
||||||
|
|
||||||
let render_options = RenderOptions {
|
let render_options = RenderOptions {
|
||||||
transform: RenderTransform::Transform2D(transform),
|
transform: RenderTransform::Transform2D(transform),
|
||||||
|
@ -204,55 +199,19 @@ pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, dpy: EGLDi
|
||||||
barrel_distortion: None,
|
barrel_distortion: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let built_options = render_options.prepare(pfs.scene.bounds);
|
let built_options = render_options.prepare(svg.scene.bounds);
|
||||||
let quad = built_options.quad();
|
let quad = built_options.quad();
|
||||||
|
let built_objects = svg.scene.build_objects(built_options, &z_buffer);
|
||||||
|
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, svg.scene.view_box);
|
||||||
|
let mut built_scene = BuiltScene::new(svg.scene.view_box, &quad, svg.scene.objects.len() as u32);
|
||||||
|
|
||||||
let built_objects = pfs.scene.build_objects(built_options, &z_buffer);
|
built_scene.shaders = svg.scene.build_shaders();
|
||||||
|
|
||||||
let mut built_scene = BuiltScene::new(pfs.scene.view_box, &quad, pfs.scene.objects.len() as u32);
|
|
||||||
built_scene.shaders = pfs.scene.build_shaders();
|
|
||||||
|
|
||||||
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, pfs.scene.view_box);
|
|
||||||
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
||||||
while let Some(batch) = scene_builder.build_batch() {
|
while let Some(batch) = scene_builder.build_batch() {
|
||||||
built_scene.batches.push(batch);
|
built_scene.batches.push(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
pfs.renderer.render_scene(&built_scene);
|
renderer.render_scene(&built_scene);
|
||||||
|
|
||||||
// let mut width = 0;
|
|
||||||
// let mut height = 0;
|
|
||||||
// let mut fbo = 0;
|
|
||||||
// egl::query_surface(dpy, surf, egl::EGL_WIDTH, &mut width);
|
|
||||||
// egl::query_surface(dpy, surf, egl::EGL_HEIGHT, &mut height);
|
|
||||||
// gl::GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fbo);
|
|
||||||
// gl::Viewport(0, 0, width, height);
|
|
||||||
// let svg_filename = CStr::from_ptr(svg_filename).to_string_lossy().into_owned();
|
|
||||||
// info!("svg={}, w={}, h={}, fbo={}.", svg_filename, width, height, fbo);
|
|
||||||
// if (app.window.dpy != dpy) || (app.window.surf != surf) {
|
|
||||||
// app.render_to_current_gl_context();
|
|
||||||
// app.window.surf = surf;
|
|
||||||
// app.window.dpy = dpy;
|
|
||||||
// }
|
|
||||||
// app.window.fbo = fbo as GLuint;
|
|
||||||
// app.window.set_size(width, height);
|
|
||||||
// app.options.background = if let Background::Dark = app.options.background {
|
|
||||||
// Background::Light
|
|
||||||
// } else {
|
|
||||||
// Background::Dark
|
|
||||||
// };
|
|
||||||
// let events = vec![
|
|
||||||
// Event::WindowResized(app.window.window_size()),
|
|
||||||
// Event::OpenSVG(SVGPath::Resource(svg_filename)),
|
|
||||||
// ];
|
|
||||||
// app.prepare_frame(events);
|
|
||||||
// app.draw_scene(0);
|
|
||||||
// app.finish_drawing_frame();
|
|
||||||
// while app.dirty {
|
|
||||||
// app.prepare_frame(vec![]);
|
|
||||||
// app.draw_scene(0);
|
|
||||||
// app.finish_drawing_frame();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue