Skip to content

Simula Godot Checklist

George Singer edited this page Jul 1, 2018 · 4 revisions

The following is a checklist/specification of needed functionality for Simula’s Godot MVP. Most of this code can be found in WindowManager.hs, Weston.hs, and ViveCompositor.hs.

Types

  1. [ ] Simula surface type. This type might include:
    • weston_desktop_surface
    • weston_view
    • Godot texture data
    • Motorcar/Wayland data (i.e., whether surface is popup, transient, cuboid, etc).
  2. [ ] Basic compositor type. This type might include:
    • Something to encode the Vive HMD node in the scene graph (the motorcar “display” type).
    • wl_display
    • weston_compositor
    • Mapping between weston_surface → Simula surface
    • weston_output
    • weston_layer associated with the compositor.
  3. [ ] A Vive compositor type. This type might include:
    • A mapping between TrackedDeviceIndex (OpenVR IDs) and (i) OpenVR models and/or (ii) weston_pointer’s
    • Something that encodes currently targetted windows (i.e., some sort of mapping between controllers, the windows that they are targetting, and where on the surface they are targetted at).
  4. [ ] Window manager type. This type might include:
    • weston_seat
    • Number of surfaces mapped in the compositor
    • OPTIONAL: A mapping between wayland surfaces and their godot nodes.
  5. [ ] Shell type. This type might include:
    • wl_display
    • wl_global (representing the shell’s advertisement in the global registry).
    • wl_global_bind_func_t (the callback used when clients bind to the global shell).
  6. [ ] ViewPoint type. (Godot probably provides something like this already; if not, see ViewPoint in old Simula codebase).

Functions

  1. [ ] newT for all Simula types T.
  2. [ ] destroyT for types T that use heap memory. See for example destroyShell in the old Simula code.
  3. [ ] A function to start the compositor.
    • Should replace weston_compositor->renderer->repaint_output with Simula’s rendering/frame updating function (analogous to Godot’s _process() or _physics_process() functions; see elsewhere in this checklist).
    • Call weston_compositor_wake.
    • Call weston_output_schedule_repaint in a loop repeatedly (in its own thread).
    • OPTIONAL: Start a loop (in its own thread) to report to console the compositor’s FPS.
    • Call wl_display_run.
  4. [ ] A function to initialize Wayland/Weston/motorcar state. A mechanism to initialize wl_* and weston_* state when the compositor starts.
    • Initialization of wl_display via wl_display_create
    • Initialization of weston_compositor via weston_compositor_create (with weston_layer_position set to WESTON_LAYER_POSITION_NORMAL)
    • Setting of weston_compositor->repaint_msec (set to 1000 ms in original Simula)
    • Call to setup_weston_log_handler for logging
    • Setting of up default XKB rules via weston_compositor_set_xkb_rule_names
    • Loading of the weston_backend_config (X11) config via weston_compositor_load_backend
    • Setting of WAYLAND_DISPLAY environment variable via wl_display_add_socket_auto
    • Loading of XWayland via weston_compositor_load_xwayland
    • Setting up of weston_windowed_output_api via weston_windowed_output_get_api
    • Ensure that Godot creates a node for the display HMD (probably happens automatically with Godot).
    • Ensure that two ViewPoints are created (one for each eye). Godot probably also does this for free, but Simula must constantly tell wayland clients where the ViewPoints are, so we probably have to keep track of this.
      • Get the projection transform of each view point (probably provided by Godot) and encode it into a wl_array to be sent to each client (encoded as a wl_resource) associated with each view point. The actual call which sends the view matrix is motorcar_viewpoint_send_projection_matrix.
    • Set up a wl_signal listener for the output pending signal, using the following callback:
      • Output pending callback/listener.
        • Set weston_output_set_scale_output <output> 1 and weston_output_set_transform <output> 0 (I’m assuming this means: don’t scale or transform the output.”).
        • Set the size of the output to 1280 x 720 via weston_windowed_output_api->output_set_size.
        • Call weston_output_enable.
    • Set up a wl_signal listener for output creation, if needed (Simula’s old output creation callback just dealt with EGL state).
    • Create a weston_output via weston_windowed_output_api->output_create
    • Create a weston_desktop_api via weston_desktop_create. Simula’s api is mostly full of null functions, with the following exceptions:
      • Surface creation callback.
        • Create a weston_view via weston_desktop_surface_create_view and associate it with the weston_output via weston_view->output.
        • Get the weston_layer of the Simula compositor (I believe set to WESTON_LAYER_POSITION_NORMAL), and use it to get its associated weston_layer->view_list, to then make a call to weston_layer_entry_insert <compositor's view list> <weston_view->layer_link> (I guess what this does is inserts the new surface’s view into the compositor layer’s view list).
        • OPTIONAL: Associate the new weston_desktop_surface with the newly created Simula surface.
      • Surface destruction callback.
        • OPTIONAL: Make sure that any Simula mapped surface is also deleted (from Simula’s compositor, window manager, etc)
        • Set weston_surface->is_mapped and weston_view->is_mapped to false.
        • Delete the surface’s node (and all of its children) from Godot’s scene graph.
        • OPTIONAL: If the surface is a motorcar surface, then handle it specially.
        • Ensure that the keyboard has proper focus (i.e., if the surface being deleted is a subsurface, then focus on the parent surface; see wmEnsureKeyboardFocusIsValid).
      • Surface committed callback.
        • Set weston_surface->is_mapped and weston_view->is_mapped to true.
        • Call weston_view_update_transform view (i.e., update the transform that sits in between the surface and the view).
        • OPTIONAL: Place the new surface in the window manager’s surface map.
        • Ensure that Godot actually renders the surface in its scene graph (see newMotorcarSurfaceNode / newWaylandSurfaceNode).
        • Adjust the surface’s size if needed, and enable motorcar options (i.e., depth compositing) if needed (use the motorcar protocol functions to update the client(s)).
        • Place the new surface at a suitable location in 3-Space and update any needed state (i.e., increment the number of tracked surfaces in the compositor by 1).
        • Make the new surface the object of the weston_pointer’s current focus.
        • If the new surface is a popup window or a transient surface, handle it appropriately (see i.e. handlePopupTransient).
        • Call weston_output_schedule_repaint against the weston_output.
    • Create a weston_pointer_grab_interface (see Simula’s defaultWestonPointerGrabInterface).
      • Set the default interface via weston_compositor_set_default_pointer_grab, using the following callbacks:
        • Pointer focus callback.
          • See Simula’s setFocusForPointer, which wraps calls to weston_pointer_set_focus and weston_keyboard_set_focus. I believe this is only relevant for when the X cursor touches a Simula window (i.e., when using Simula in non-HMD mode).
        • Button event callback.
          • See Simula’s setFocusForPointer, which wraps calls to weston_pointer_set_focus and weston_keyboard_set_focus. I believe this is only relevant for when the X cursor touches a Simula window (i.e., when using Simula in non-HMD mode).
          • Call weston_pointer_send_button.
    • Set the SIGUSR1 POSIX signal handler to do nothing (so that XWayland can function properly); then load XWayland via wet_load_xwayland.
  5. [ ] A function that extracts a (Godot?) texture from a =weston_surface=.
  6. [ ] A function that ensures weston subsurfaces are rendered by Godot. See i.e., composeSurface and paintChildren in the old Simula code.
  7. [ ] A frame rendering/state updating function that can be inserted into =weston_compositor->renderer->repaint_output=.
    • Ensure that all client view_matrix’s and projection_matrix’s are updated (for each viewpoint associated with the HMD display in the Godot scene graph).
      • More specifically: get the world-space transform of each view point and compute its lookAt matrix (i.e., the affine transform that converts world coordinates to view space coordinates). Then, take this view matrix and encode it into a wl_array, to send to each client (encoded as a wl_resource) associated with the view point. The actual call which sends the view matrix is motorcar_viewpoint_send_view_matrix.
    • Call weston_outout_schedule_repaint
    • Ensure that all of weston surfaces (and their subsurfaces) are properly rendered.
    • Emit the output frame signal (weston_output->frame_signal) via a call to wl_signal_emit <output frame signal>.
  8. [ ] A Vive compositor type.
    • A mapping between TrackedDeviceIndex (OpenVR IDs) and (i) OpenVR models and/or (ii) weston_pointer’s
    • Something that encodes currently targetted windows (i.e., some sort of mapping between controllers, the windows that they are targetting, and where on the surface they are targetted at).
  9. [ ] A function that converts OpenVR button events to weston activity. This function should take an HMD controller and its associated weston_pointer to
    • Wrap a call to pointer_send_motion.
    • Update the list of targetted windows/surfaces.
    • Add/Remove surfaces from list of targetted windows if the grip button is pressed/unpressed.
    • If the trigger button is pressed, wrap a call to weston_pointer_set_focus, weston_keyboard_set_focus, and notify_button.
  10. [ ] A utility function to create a Simula surface (on top of a new godot node) and to add it to the window manager’s mapping between weston surfaces and godot nodes.
  11. [ ] A utility function to destroy Simula surfaces. This function should do the following:
    • Destroy the surface node (and all of its children) from Godot’s scene graph (in particular: make sure to recursively call this function on all of the node’s subsurface nodes).
    • Delete the surface from the window manager’s mapping between surfaces and Godot nodes.
    • OPTIONAL: If the node is a motorcar surface, then handle it specially (see destroyMotorcarSurfaceNode; note this is not currently being used in the old Simula codebase).
    • Ensure that the weston_pointer is de-focused, and that the weston_keyboard has proper focus on the next available surface (see wmEnsureKeyboardFocusIsValid, whose inner working are somewhat opaque to me; it looks like it might not involve many inner wayland/weston calls?).
  12. [ ] A function to create a Simula Shell and add it to the weston global registry (with motorcar interface functions implemented). This function should wrap a call to
    wl_global_create(<Simula's wl_display>, 
                     <motorcar shell wl_interface>, 
                     <motorcar shell version int>, 
                     <Simula Shell type>, 
                     <client Shell binding function of type wl_global_bind_func_t>);
        

    where the shell binding function does the following:

    1. Creates a wl_resource via
      wl_resource_create(<client>,
                        <motorcar shell wl_interface>,
                        <motorcar interface version>,
                        <resource uint32_t id> );
              
    2. Then sets the implementation via:
      wl_resource_set_implementation(<the created wl_resource>,
                                    <struct containing getMotorcarSurface>,
                                    <Simula Shell>,
                                    <A null pointer for wl_resource_destroy_func_t>
      );
              

    where getMotorcarSurface is a function that does the following:

    • (Ensure that there is a godot node associated with the motorcar/Simula surface).
    • Makes call to wl_resource_create … <motorcar surface interface> <motorcar surface version> …
    • Makes call to wl_resource_set_implementation <wl_resource from above> <set_size_3d struct> <data argument/godot node> <wl_resource_Destroy_func_t> Here “set_size_3d struct” is a struct that contains a function which does the following:
      • Takes a motorcar surface and a V3, and then scale’s the MotorcarSurfaceNode by the V3 (force setting the third coordinate to 0 if portal mode is enabled for the motorcar surface).
      • Makes a call to motorcar_surface_send_transform_matrix <wl_resource/client> <model space → world space transform in the form of a wl_array>
  13. [ ] A function to create a Simula ViewPoint and add it to the weston global registry (with motorcar interface functions implemented). This function should do the following:
    • First wrap a call to
    wl_global_create(<Simula compositor's wl_display>, 
                      <motorcar_viewpoint wl_interface>, 
                      <motorcar_viewpoint version int>, 
                      <The actual ViewPoint>, 
                      <client viewpoint binding function of type wl_global_bind_func_t>); //see below
        
    • Then we should update the ViewPoint’s view matrix (also called the “lookAt” matrix, which takes world coordinates to view coordinates) and send to clients via a call to motorcar_viewpoint_send_view_matrix <wl_resource> <view matrix in form wl_array> (do this for each wl_resource associated with the ViewPoint).
    • Then we should update the ViewPoint’s projection matrix and send to clients via a call to motorcar_viewpoint_send_projection_matrix <wl_resource> <projection matrix in form wl_array> (for each wl_resource associated with the ViewPoint).
    • Finally we should update the ViewPoint’s view port and send to clients via a call to motorcar_viewpoint_send_view_port <wl_resource> …viewpoint data… (for each wl_resource associated with the ViewPoint).
  14. Client viewpoint binding function. Here is how to populate the wl_global_bind_func_t argument of wl_global_create:
    • Create a wl_resource via
      wl_resource_create(<client>,
                        <motorcar_viewpoint wl_interface>,
                        <motorcar_viewpoint interface version>,
                        <resource uint32_t id> );
              
    • Then set the implementation via:
      wl_resource_set_implementation(<the created wl_resource>,
                                    <nullPtr implementation>, //i.e., empty implementation
                                    <Simula ViewPoint>,
                                    <motorcar_viewpoint destruction function of type wl_resource_destroy_func_t>
      );
              

      where the destruction function (optionally) does the following:

      • Takes the wl_resource argument and retrieves the Simula ViewPoint from wl_resource->data.
      • Removes any references to the wl_resource from the ViewPoint (in old Simula code, ViewPoint had a field called viewPointResources which tracked this).
      • Wraps calls to the following motorcar protocol functions:
      motorcar_viewpoint_send_view_matrix(<wl_resource>, <ViewPoint's view matrix>);
      motorcar_viewpoint_send_projection_matrix(<wl_resource>, <ViewPoint's projection_matrix>);
      motorcar_viewpoint_send_view_port(<wl_resource>, …viewport data…);