Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skia OpenGL Context is Broken Compared to FemtoVG #7845

Open
bryce-happel-walton opened this issue Mar 11, 2025 · 0 comments
Open

Skia OpenGL Context is Broken Compared to FemtoVG #7845

bryce-happel-walton opened this issue Mar 11, 2025 · 0 comments
Labels
bug Something isn't working need triaging Issue that the owner of the area still need to triage

Comments

@bryce-happel-walton
Copy link

bryce-happel-walton commented Mar 11, 2025

Bug Description

While I was experimenting with the open gl context in order to implement the three-d library, I found that Skia completely breaks down while FemtoVG works as expected.

FemtoVG:
Image

Skia:
Image
Skia in my actual application:
Image

The image only shows the little image rectangle, but the entire application is flashing at the framerate. My Slint ui is missing/broken.

Under Skia, the window will randomly crash with different errors every time.

Reproducible Code

export component App inherits Window {
    in property <image> threed-widget-texture <=> threed-container-image.source;
    out property <length> threed-widget-width: threed-container-image.width;
    out property <length> threed-widget-height: threed-container-image.height;
    out property <length> threed-widget-x: threed-container-image.absolute-position.x;
    out property <length> threed-widget-y: threed-container-image.absolute-position.y;

    preferred-width: 500px;
    preferred-height: 600px;
    title: "Slint OpenGL Texture Example";

    threed-container-image := Image {
        width: 100%;
        height: 100%;
    }
}
use std::sync::Arc;
use three_d::{context::*, *};

slint::include_modules!();

struct ModelContainer {
    context: three_d::Context,
    model: Gm<Mesh, ColorMaterial>,
}

impl ModelContainer {
    pub fn new(context: three_d::Context) -> Self {
        let cpu_mesh = CpuMesh {
            positions: Positions::F32(vec![
                vec3(0.5, -0.5, 0.0),  // bottom right
                vec3(-0.5, -0.5, 0.0), // bottom left
                vec3(0.0, 0.5, 0.0),   // top
            ]),
            colors: Some(vec![
                Srgba::new(255, 0, 0, 255), // bottom right
                Srgba::new(0, 255, 0, 255), // bottom left
                Srgba::new(0, 0, 255, 255), // top
            ]),
            ..Default::default()
        };

        let model = Gm::new(Mesh::new(&context, &cpu_mesh), ColorMaterial::default());

        Self { context, model }
    }

    pub fn render(&self, width: u32, height: u32) -> slint::Image {
        let context = &self.context;

        unsafe {
            let texture = context.create_texture().unwrap();
            context.bind_texture(TEXTURE_2D, Some(texture));
            context.tex_image_2d(
                TEXTURE_2D,
                0,
                RGBA as _,
                width as _,
                height as _,
                0,
                RGBA,
                UNSIGNED_BYTE,
                three_d::context::PixelUnpackData::Slice(None),
            );
            context.tex_parameter_i32(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR as _);
            context.tex_parameter_i32(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR as _);

            let framebuffer = context.create_framebuffer().unwrap();
            context.bind_framebuffer(FRAMEBUFFER, Some(framebuffer));
            context.framebuffer_texture_2d(
                FRAMEBUFFER,
                COLOR_ATTACHMENT0,
                TEXTURE_2D,
                Some(texture),
                0,
            );

            let renderer = RenderTarget::from_framebuffer(context, width, height, framebuffer);

            let camera = Camera::new_perspective(
                renderer.viewport(),
                vec3(0.0, 0.0, 2.0),
                vec3(0.0, 0.0, 0.0),
                vec3(0.0, 1.0, 0.0),
                degrees(45.0),
                0.1,
                10.0,
            );

            renderer.clear(ClearState::color_and_depth(0.8, 0.8, 0.8, 1.0, 1.0));
            renderer.render(camera, &self.model, &[]);

            slint::BorrowedOpenGLTextureBuilder::new_gl_2d_rgba_texture(
                texture.0,
                (width as _, height as _).into(),
            )
            .build()
        }
    }
}

fn main() {
    let app = App::new().unwrap();
    let weak_app = app.as_weak();
    let mut model_container = None;

    app.window()
        .set_rendering_notifier(move |state, graphics_api| match state {
            slint::RenderingState::RenderingSetup => {
                let gl_context = match graphics_api {
                    slint::GraphicsAPI::NativeOpenGL { get_proc_address } => unsafe {
                        three_d::context::Context::from_loader_function_cstr(get_proc_address)
                    },
                    _ => return,
                };

                if let Ok(context) = three_d::Context::from_gl_context(Arc::new(gl_context)) {
                    model_container = Some(ModelContainer::new(context));
                }
            }
            slint::RenderingState::BeforeRendering => {
                if let (Some(model_container), Some(app)) = (&model_container, weak_app.upgrade()) {
                    let image = model_container.render(
                        app.get_threed_widget_width() as _,
                        app.get_threed_widget_height() as _,
                    );
                    app.set_threed_widget_texture(image);
                    app.window().request_redraw();
                }
            }
            _ => {}
        })
        .unwrap();
    app.run().unwrap();
}

Environment Details

  • Slint Version: 1.10.0
  • Platform/OS: Fedora Linux 41 | NVidia 570.86.16 | Wayland
  • Programming Language: Rust
  • Backend/Renderer: FemtoVG | Skia

Product Impact

I use Skia because the Path objects behave as expected and I utilize them heavily. FemtoVG Paths produce completely different results from Skia. I need the Paths and use of the gl context for other libraries, so this is a major blocker.

@bryce-happel-walton bryce-happel-walton added bug Something isn't working need triaging Issue that the owner of the area still need to triage labels Mar 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working need triaging Issue that the owner of the area still need to triage
Projects
None yet
Development

No branches or pull requests

1 participant