Skip to content

Library doesn't work with Gtk under Wayland #1416

@Nokse22

Description

@Nokse22

Describe the bug
I tried to use libf3d with python and Gtk, but it doesn't render and it crashes

To Reproduce
Steps to reproduce the behavior:

  1. Run the provided python code
  2. Open a 3d file
  3. It won't render and it will crash after resizing the window.

Expected behavior
It should render correctly inside the Gtk.GLArea, if I render it outside it works.

System Information:

  • OS: Fedora 40
  • GPU and GPU driver: AMD Radeon™ Graphics

F3D Information
The version of f3d library is 2.4.0 installed with pip

Additional context

import gi
import f3d

gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')

from gi.repository import Gtk, Adw

class F3Dwindow(Adw.ApplicationWindow):
    __gtype_name__ = 'F3Dwindow'

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        self.set_default_size(300, 300)
        self.set_title("F3D")
        
        self.gl_area = Gtk.GLArea(vexpand=True)
        self.gl_area.connect("realize", self.on_realize)
        self.gl_area.connect("render", self.on_render)
        
        box = Gtk.Box(orientation=1)
        
        button = Gtk.Button(label="open")
        button.connect("clicked", self.open_file_chooser)
        
        hb = Adw.HeaderBar()
        hb.pack_start(button)
        
        box.append(hb)
        box.append(self.gl_area)
        
        self.set_content(box)
        
        f3d.Engine.autoload_plugins()
        self.engine = f3d.Engine(f3d.Window.EXTERNAL)
    
    def on_realize(self, area):
        ctx = area.get_context()

    def on_render(self, area, ctx):
        ctx.make_current()
        self.engine.window.render()
        
        print(area.get_error())
        
        return True

    def open_file_chooser(self, *args):
        dialog = Gtk.FileDialog(
            title="Open File",
        )
        dialog.open(self, None, self.on_open_file_response)

    def on_open_file_response(self, dialog, response):
        file = dialog.open_finish(response)
        print(f"Selected File: {file.get_path()}")

        if file:
            filepath = file.get_path()
            self.engine.loader.load_geometry(filepath)
    
        
class F3Dapp(Adw.Application):
    def __init__(self):
        super().__init__()

    def do_activate(self):
        win = self.props.active_window
        if not win:
            win = F3Dwindow(application=self)
        win.present()

def main():
    app = F3Dapp()
    return app.run()

main()

This code should show an application window with a button to open a 3d model file and a Gtk.GLArea where to render the 3d model.

Every time it renders it prints this:

Current framebuffer is bind to framebuffer object 85
color attachment 0:
 this attachment is a texture with name: 166
 its mipmap level is: 0
 this is not a cube map texture.
 this is not 3D texture.
color attachment 1:
 this attachment is empty
color attachment 2:
 this attachment is empty
color attachment 3:
 this attachment is empty
color attachment 4:
 this attachment is empty
color attachment 5:
 this attachment is empty
color attachment 6:
 this attachment is empty
color attachment 7:
 this attachment is empty
depth attachment :
 this attachment is a texture with name: 167
 its mipmap level is: 0
 this is not a cube map texture.
 this is not 3D texture.
stencil attachment :
 this attachment is empty
there are 8 draw buffers. 
draw buffer[0]=GL_COLOR_ATTACHMENT0
draw buffer[1]=GL_NONE
draw buffer[2]=GL_NONE
draw buffer[3]=GL_NONE
draw buffer[4]=GL_NONE
draw buffer[5]=GL_NONE
draw buffer[6]=GL_NONE
draw buffer[7]=GL_NONE
read buffer=GL_COLOR_ATTACHMENT0

And the result of print(area.get_error()) at line 45 before crashing is:

Segmentation fault (core dumped)

Otherwise is None


I can correctly draw using OpenGL like this and it won't crash:

import gi
import f3d

from OpenGL.GL import *
from OpenGL.GLU import *

[...]

    def on_render(self, area, ctx):
        # self.engine.window.render()
        
        glClearColor(1,0,0,1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        
        print(area.get_error())
        
        return True

[...]

If I do this:

[...]

    def on_render(self, area, ctx):
        img = self.engine.window.render_to_image()

        img.save("/home/user/image.png")
        
        print(area.get_error())
        
        return True

[...]

It will save an image of the same size of the Gtk.GLArea, but all black if no model is loaded or an image like the following one if a geometry is loaded.

image


With Gtk.GLArea I can set the allowed APIs with:

self.gl_area.set_allowed_apis(Gdk.GLAPI.GL)
self.gl_area.set_allowed_apis(Gdk.GLAPI.GLES)

With only GL it will not crash and it will not print anything, with GLES it will.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions