ux-dx 0.2.1

3D Graphics Primitives for Angular Rust
Documentation
#![allow(
    clippy::too_many_arguments,
    clippy::let_and_return,
    clippy::from_over_into
)]

use super::{Driver, OnscreenTemplate, Output, RendererConstraint, WinsysID};
use std::{fmt, ptr};

// typedef struct _DriverDescription
// {
//   Driver id;
//   const char *name;
//   RendererConstraint constraints;
//   /* It would be nice to make this a pointer and then use a compound
//    * literal from C99 to initialise it but we probably can't get away
//    * with using C99 here. Instead we'll just use a fixed-size array.
//    * GCC should complain if someone adds an 8th feature to a
//    * driver. */
//   const PrivateFeature private_features[8];
//   const DriverVtable *vtable;
//   const TextureDriver *texture_driver;
//   const char *libgl_name;
// } DriverDescription;

// @short_description: Choosing a means to render
//
// A #Renderer represents a means to render. It encapsulates the
// selection of an underlying driver, such as OpenGL or OpenGL-ES and
// a selection of a window system binding API such as GLX, or EGL or
// WGL.
//
// A #Renderer has two states, "unconnected" and "connected". When
// a renderer is first instantiated using renderer_new() it is
// unconnected so that it can be configured and constraints can be
// specified for how the backend driver and window system should be
// chosen.
//
// After configuration a #Renderer can (optionally) be explicitly
// connected using renderer_connect() which allows for the
// handling of connection errors so that fallback configurations can
// be tried if necessary. Applications that don't support any
// fallbacks though can skip using renderer_connect() and leave
//  to automatically connect the renderer.
//
// Once you have a configured #Renderer it can be used to create a
// #Display object using display_new().
//
// Many applications don't need to explicitly use
// renderer_new() or display_new() and can just jump
// straight to context_new() and pass a %NULL display argument so
//  will automatically connect and setup a renderer and
// display.
#[derive(Default, Debug, Clone)]
pub struct Renderer {
    connected: bool,
    driver_override: Driver,
    // const DriverVtable *driver_vtable;
    // const TextureDriver *texture_driver;
    // const WinsysVtable *winsys_vtable;
    // WinsysID winsys_id_override;
    // GList *constraints;

    // GArray *poll_fds;
    poll_fds_age: i32,
    // GList *poll_sources;

    // List idle_closures;

    // GList *outputs;
    #[cfg(feature = "xlib")]
    foreign_xdpy: Option<Display>,
    #[cfg(feature = "xlib")]
    xlib_enable_event_retrieval: bool,

    #[cfg(feature = "win32")]
    win32_enable_event_retrieval: bool,

    driver: Driver,
    // unsigned long private_features
    //     [FLAGS_N_LONGS_FOR_SIZE (N_PRIVATE_FEATURES)];
    #[cfg(feature = "directly_linked_gl_library")]
    libgl_module: Option<GModule>,

    #[cfg(feature = "egl_platform_wayland")]
    foreign_wayland_display: Option<wl_display>,
    #[cfg(feature = "egl_platform_wayland")]
    wayland_enable_event_dispatch: bool,

    #[cfg(feature = "egl_platform_mir")]
    foreign_mir_connection: Option<MirConnection>,

    #[cfg(feature = "egl_platform_kms")]
    kms_fd: i32,

    #[cfg(feature = "sdl")]
    sdl_event_type_set: bool,
    #[cfg(feature = "sdl")]
    sdl_event_type: u32,
    // List of callback functions that will be given every native event

    // GSList *event_filters;
    // void *winsys;
}

impl Renderer {
    /// Instantiates a new (unconnected) `Renderer` object:: A
    /// `Renderer` represents a means to render. It encapsulates the
    /// selection of an underlying driver, such as OpenGL or OpenGL-ES and
    /// a selection of a window system binding API such as GLX, or EGL or
    /// WGL.
    ///
    /// While the renderer is unconnected it can be configured so that
    /// applications may specify backend constraints, such as "must use
    /// x11" for example via `Renderer::add_constraint`.
    ///
    /// There are also some platform specific configuration apis such
    /// as `xlib_renderer_set_foreign_display` that may also be
    /// used while the renderer is unconnected.
    ///
    /// Once the renderer has been configured, then it may (optionally) be
    /// explicitly connected using `Renderer::connect` which allows
    /// errors to be handled gracefully and potentially fallback
    /// configurations can be tried out if there are initial failures.
    ///
    /// If a renderer is not explicitly connected then `Display::new`
    /// will automatically connect the renderer for you. If you don't
    /// have any code to deal with error/fallback situations then its fine
    /// to just let  do the connection for you.
    ///
    /// Once you have setup your renderer then the next step is to create a
    /// `Display` using `Display::new`.
    ///
    /// Many applications don't need to explicitly use
    /// `Renderer::new` or `Display::new` and can just jump
    /// straight to `Context::new` and pass a `None` display argument
    /// so  will automatically connect and setup a renderer and
    /// display.
    ///
    /// # Returns
    ///
    /// A newly created `Renderer`.
    pub fn new() -> Renderer {
        super::init();

        let renderer = Self::default();

        // self.poll_fds = g_array_new (false, true, sizeof (PollFD));

        // _list_init (&self.idle_closures);

        // #[cfg(feature = "xlib")]
        // renderer.xlib_enable_event_retrieval = true;

        // #[cfg(feature = "win32")]
        // renderer.win32_enable_event_retrieval = true;

        // #[cfg(feature = "egl_platform_wayland")]
        // renderer.wayland_enable_event_dispatch = true;

        // #[cfg(feature = "egl_platform_kms")]
        // renderer.kms_fd = -1;

        renderer
    }

    /// This adds a renderer selection `constraint`.
    ///
    /// Applications should ideally minimize how many of these constraints they
    /// depend on to ensure maximum portability.
    /// ## `constraint`
    /// A `RendererConstraint` to add
    pub fn add_constraint(&self, constraint: RendererConstraint) {
        // g_return_if_fail (!self.connected);
        // self.constraints = g_list_prepend (self.constraints,
        //                                   GUINT_TO_POINTER (constraint));
        unimplemented!()
    }

    /// Tests if a given `onscreen_template` can be supported with the given
    /// `self`.
    /// ## `onscreen_template`
    /// A `OnscreenTemplate`
    ///
    /// # Returns
    ///
    /// `true` if the `onscreen_template` can be supported,
    ///  else `false`.
    pub fn check_onscreen_template(&self, onscreen_template: &OnscreenTemplate) -> bool {
        // Display *display;

        // if (!renderer_connect (renderer, error))
        //     return false;

        // display = display_new (renderer, onscreen_template);
        // if !display_setup(display, error) {
        //     object_unref (display);
        //     return false;
        // }

        // object_unref (display);

        // return true;
        unimplemented!()
    }

    /// Connects the configured `self`. Renderer connection isn't a
    /// very active process, it basically just means validating that
    /// any given constraint criteria can be satisfied and that a
    /// usable driver and window system backend can be found.
    ///
    /// # Returns
    ///
    /// `true` if there was no error while connecting the
    ///  given `self`. `false` if there was an error.
    pub fn connect(&self) -> bool {
        // int i;
        // GString *error_message;
        // Bool constraints_failed = false;

        if self.connected {
            return true;
        }

        // The driver needs to be chosen before connecting the renderer
        // because eglInitialize requires the library containing the GL API
        // to be loaded before its called

        // if !_renderer_choose_driver(renderer, error) {
        //     return false;
        // }

        // error_message = g_string_new ("");
        // for (i = 0; i < G_N_ELEMENTS (_winsys_vtable_getters); i++) {
        //     const WinsysVtable *winsys = _winsys_vtable_getters[i]();
        //     Error *tmp_error = NULL;
        //     GList *l;
        //     let skip_due_to_constraints = false;

        //     if self.winsys_id_override != WINSYS_ID_ANY {
        //         if (self.winsys_id_override != winsys->id)
        //             continue;
        //     } else {
        //         char *user_choice = getenv ("RENDERER");
        //         if !user_choice {
        //             user_choice = _config_renderer;
        //         }
        //         if user_choice &&
        //             g_ascii_strcasecmp (winsys->name, user_choice) != 0 {
        //             continue;
        //         }
        //     }

        //     for (l = self.constraints; l; l = l->next) {
        //         RendererConstraint constraint = GPOINTER_TO_UINT (l->data);
        //         if !(winsys->constraints & constraint) {
        //             skip_due_to_constraints = true;
        //             break;
        //         }
        //     }
        //     if skip_due_to_constraints {
        //         constraints_failed |= true;
        //         continue;
        //     }

        // At least temporarily we will associate this winsys with
        // the renderer in-case ->renderer_connect calls API that
        // wants to query the current winsys...

        //     self.winsys_vtable = winsys;

        //     if !winsys->renderer_connect (renderer, &tmp_error) {
        //         g_string_append_c (error_message, '\n');
        //         g_string_append (error_message, tmp_error->message);
        //         error_free (tmp_error);
        //     } else {
        //         self.connected = true;
        //         g_string_free (error_message, true);
        //         return true;
        //     }
        // }

        if !self.connected {
            // if constraints_failed {
            //     _set_error (error, RENDERER_ERROR,
            //                 RENDERER_ERROR_BAD_CONSTRAINT,
            //                 "Failed to connected to any renderer due to constraints");
            //     return false;
            // }

            // self.winsys_vtable = NULL;
            // _set_error (error, WINSYS_ERROR,
            //             WINSYS_ERROR_INIT,
            //             "Failed to connected to any renderer: %s",
            //             error_message->str);
            // g_string_free (error_message, true);
            // return false;
        }

        true
    }

    /// Iterates all known display outputs for the given `self` and
    /// passes a corresponding `Output` pointer to the given `callback`
    /// for each one, along with the given `user_data`.
    /// ## `callback`
    /// A `OutputCallback` to be called for
    ///  each display output
    /// ## `user_data`
    /// A user pointer to be passed to `callback`
    pub fn foreach_output<P: FnMut(&Output)>(&self, callback: P) {
        // GList *l;

        // _RETURN_IF_FAIL (self.connected);
        // _RETURN_IF_FAIL (callback != NULL);

        // for (l = self.outputs; l; l = l->next)
        //   callback (l->data, user_data);
        unimplemented!()
    }

    /// Queries what underlying driver is being used by .
    ///
    /// This may only be called on a connected `Renderer`.
    pub fn driver(&self) -> Driver {
        // _RETURN_VAL_IF_FAIL (self.connected, 0);

        // return self.driver;
        unimplemented!()
    }

    /// Queries how many texture units can be used from fragment programs
    ///
    /// # Returns
    ///
    /// the number of texture image units.
    pub fn n_fragment_texture_units(&self) -> i32 {
        // int n = 0;

        //     _GET_CONTEXT (ctx, 0);

        // #if defined (HAVE_GL) || defined (HAVE_GLES2)
        //     if (has_feature (ctx, FEATURE_ID_GLSL) ||
        //         has_feature (ctx, FEATURE_ID_ARBFP))
        //     GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n));
        // #endif

        // return n;
        unimplemented!()
    }

    /// Queries which window system backend  has chosen to use.
    ///
    /// This may only be called on a connected `Renderer`.
    ///
    /// # Returns
    ///
    /// The `WinsysID` corresponding to the chosen window
    ///  system backend.
    pub fn winsys_id(&self) -> WinsysID {
        // _RETURN_VAL_IF_FAIL (self.connected, 0);

        // return self.winsys_vtable->id;
        unimplemented!()
    }

    /// This removes a renderer selection `constraint`.
    ///
    /// Applications should ideally minimize how many of these constraints they
    /// depend on to ensure maximum portability.
    /// ## `constraint`
    /// A `RendererConstraint` to remove
    pub fn remove_constraint(&self, constraint: RendererConstraint) {
        // g_return_if_fail (!self.connected);
        // self.constraints = g_list_remove (self.constraints,
        //                                        GUINT_TO_POINTER (constraint));
        unimplemented!()
    }

    /// Requests that  should try to use a specific underlying driver
    /// for rendering.
    ///
    /// If you select an unsupported driver then `Renderer::connect`
    /// will fail and report an error. Most applications should not
    /// explicitly select a driver and should rely on  automatically
    /// choosing the driver.
    ///
    /// This may only be called on an un-connected `Renderer`.
    pub fn set_driver(&self, driver: Driver) {
        // _RETURN_IF_FAIL (!self.connected);
        // self.driver_override = driver;
        unimplemented!()
    }

    /// This allows you to explicitly select a winsys backend to use instead
    /// of letting  automatically select a backend.
    ///
    /// if you select an unsupported backend then `Renderer::connect`
    /// will fail and report an error.
    ///
    /// This may only be called on an un-connected `Renderer`.
    /// ## `winsys_id`
    /// An ID of the winsys you explicitly want to use.
    pub fn set_winsys_id(&self, winsys_id: WinsysID) {
        // _RETURN_IF_FAIL (!self.connected);

        // self.winsys_id_override = winsys_id;
        unimplemented!()
    }
}

impl fmt::Display for Renderer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Renderer")
    }
}