gfx-gtk

Simple bridge library to render into a gtk-rs GLArea using the Gfx (pre-ll) library.

Uses [epoxy] for Gl loading, and as such it doesn't require a Gl window/loading management such as glutin or winit

Here's a short broken-down list to get the integration up and running:

Add the Cargo dependencies

[dependencies] gfx_gtk = "0.3"

Import crate and packages

```rust extern crate gfx_gtk;

use gfxgtk::formats; use gfxgtk::GlRenderContext; ```

Choose some render formats and AA mode

rust const MSAA: gfx::texture::AaMode = formats::MSAA_4X; type RenderColorFormat = formats::DefaultRenderColorFormat; type RenderDepthFormat = formats::DefaultRenderDepthFormat;

Write a render callback

You need to implement [GlRenderCallback] and [GlPostprocessCallback] traits (the latter can be made to use the default implementation)

```rust struct SimpleRenderCallback { ... }

impl gfxgtk::GlRenderCallback for SimpleRenderCallback { fn render( &mut self, gfxcontext: &mut gfxgtk::GlGfxContext, viewport: &gfxgtk::Viewport, framebuffer: &gfxgtk::GlFrameBuffer, depthbuffer: &gfxgtk::GlDepthBuffer, ) -> gfxgtk::Result { gfxcontext.encoder.draw(...); Ok(gfx_gtk::GlRenderCallbackStatus::Continue) } }

impl gfx_gtk::GlPostprocessCallback for SimpleRenderCallback {} ```

Load Gl functions

```rust gfx_gtk::load();

```

Connect the widget's signals

The rendering needs to be driven by a GlArea widget because of its ability to create a Gl context.

The realize, resize and render signals need to be connected. The [GlRenderContext] and [GlRenderCallback] must be created in the closure that gets attached to GlArea::connect_realize() after the make_current() call (otherwise it won't be possible to "bind" to the current GlArea Gl context

```rust let gfx_context: Rc>>> = Rc::new(RefCell::new(None));

let render_callback: Rc>> = Rc::new(RefCell::new(None));

let glarea = gtk::GLArea::new();

glarea.connectrealize({ let gfxcontext = gfxcontext.clone(); let rendercallback = render_callback.clone();

move |widget| {
    if widget.get_realized() {
        widget.make_current();
    }

    let allocation = widget.get_allocation();

    let mut new_context =
        gfx_gtk::GlRenderContext::new(
        MSAA,
        allocation.width,
        allocation.height,
        None).ok();
    if let Some(ref mut new_context) = new_context {
        let ref vp = new_context.viewport();
        let ref mut ctx = new_context.gfx_context_mut();
        *render_callback.borrow_mut() = SimpleRenderCallback::new(ctx, vp).ok();
    }
    *gfx_context.borrow_mut() = new_context;
}

});

glarea.connectresize({ let gfxcontext = gfxcontext.clone(); let rendercallback = render_callback.clone();

move |_widget, width, height| {
    if let Some(ref mut context) = *gfx_context.borrow_mut() {
        if let Some(ref mut render_callback) = *render_callback.borrow_mut() {
            context.resize(width, height, Some(render_callback)).ok();
        }
    }
}

});

glarea.connectrender({ let gfxcontext = gfxcontext.clone(); let rendercallback = render_callback.clone();

move |_widget, _gl_context| {
    if let Some(ref mut context) = *gfx_context.borrow_mut() {
        if let Some(ref mut render_callback) = *render_callback.borrow_mut() {
            context.with_gfx(render_callback);
        }
    }

    Inhibit(false)
}

}); `` After this, every time Gtk refreshes theGlAreacontent, it will invoke therender_callback` to paint itself.

See examples/setup.rs for a simple interactive rendering example. On running it with cargo run --example setup, it should look like this:

Screenshot 1

© 2018 Nico Orru https://www.itadinanta.net