--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Gamnit display implementation for GNU/Linux using `egl`, `sdl` and `x11`
+module display_linux
+
+import sdl
+import x11
+
+import egl # local to gamnit
+import display
+
+redef class GamnitDisplay
+
+ # Actual width or desired width of the window, can be set before calling `setup`
+ fun width=(value: Int) do requested_width = value
+ private var requested_width = 1920
+
+ # Actual height or desired height of the window, can be set before calling `setup`
+ fun height=(value: Int) do requested_height = value
+ private var requested_height = 1080
+
+ # Setup SDL, X11, EGL in order
+ redef fun setup
+ do
+ if debug_gamnit then print "Setting up SDL"
+ self.sdl_display = setup_sdl(requested_width, requested_height)
+
+ if debug_gamnit then print "Setting up X11"
+ var x11_display = setup_x11
+ var window_handle = window_handle
+ setup_egl_display x11_display
+
+ if debug_gamnit then print "Setting up EGL context"
+ select_egl_config(8, 8, 8, 8, 8, 0, 0)
+ setup_egl_context window_handle
+ end
+
+ # Close EGL and SDL in reverse order of `setup` (nothing to do for X11)
+ redef fun close
+ do
+ close_egl
+ close_sdl
+ end
+
+ # ---
+ # SDL
+
+ # The SDL display managing the window and events
+ var sdl_display: SDLDisplay is noautoinit
+
+ # Setup the SDL display and lib
+ fun setup_sdl(window_width, window_height: Int): SDLDisplay
+ do
+ var sdl_display = new SDLDisplay(window_width, window_height)
+ assert not sdl_display.address_is_null else print "Opening SDL display failed"
+ return sdl_display
+ end
+
+ # Close the SDL display
+ fun close_sdl do sdl_display.destroy
+
+ # Get a native handle to the current SDL window
+ fun window_handle: Pointer
+ do
+ var sdl_wm_info = new SDLSystemWindowManagerInfo
+ return sdl_wm_info.x11_window_handle
+ end
+
+ # ---
+ # X11
+
+ # Get a native handle to the current X11 display
+ fun setup_x11: Pointer
+ do
+ var x11_display = x_open_default_display
+ assert not x11_display.address_is_null else print "Opening X11 display failed"
+ return x11_display
+ end
+end
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Use of EGL to implement Gamnit on GNU/Linux and Android
+module egl
+
+import ::egl
+
+import gamnit::display
+
+redef class GamnitDisplay
+
+ # The EGL display
+ var egl_display: EGLDisplay is noautoinit
+
+ # The EGL context
+ var egl_context: EGLContext is noautoinit
+
+ # The EGL surface for the window
+ var window_surface: EGLSurface is noautoinit
+
+ # The selected EGL configuration
+ var egl_config: EGLConfig is noautoinit
+
+ # Setup the EGL display for the given `x11_display`
+ protected fun setup_egl_display(x11_display: Pointer)
+ do
+ var egl_display = new EGLDisplay(x11_display)
+ assert egl_display.is_valid else print "new EGL display is not valid"
+
+ egl_display.initialize
+ assert egl_display.is_valid else print "EGL initialize error: {egl_display.error}"
+
+ self.egl_display = egl_display
+ end
+
+ # Select an EGL config
+ protected fun select_egl_config(blue, green, red, alpha, depth, stencil, sample: Int)
+ do
+ var config_chooser = new EGLConfigChooser
+ config_chooser.renderable_type_egl
+ config_chooser.surface_type_egl
+ config_chooser.blue_size = blue
+ config_chooser.green_size = green
+ config_chooser.red_size = red
+ if alpha > 0 then config_chooser.alpha_size = alpha
+ if depth > 0 then config_chooser.depth_size = depth
+ if stencil > 0 then config_chooser.stencil_size = stencil
+ if sample > 0 then config_chooser.sample_buffers = sample
+ config_chooser.close
+
+ var configs = config_chooser.choose(egl_display)
+ assert configs != null else print "Choosing EGL config failed: {egl_display.error}"
+ assert not configs.is_empty else print "Found no EGL config"
+
+ if debug_gamnit then
+ print "EGL available configurations:"
+ for config in configs do
+ var attribs = config.attribs(egl_display)
+ print "* Conformant to: {attribs.conformant}"
+ print " Caveats: {attribs.caveat}"
+ print " Size of RGBA: {attribs.red_size} {attribs.green_size} {attribs.blue_size} {attribs.alpha_size}"
+ print " Buffer, depth, stencil: {attribs.buffer_size} {attribs.depth_size} {attribs.stencil_size}"
+ end
+ end
+
+ # We use the first one, it is recommended
+ self.egl_config = configs.first
+ end
+
+ # Setup the EGL context for the given `window_handle`
+ protected fun setup_egl_context(window_handle: Pointer)
+ do
+ var window_surface = egl_display.create_window_surface(egl_config, window_handle, [0])
+ assert window_surface.is_ok else print "Creating EGL window surface failed: {egl_display.error}"
+ self.window_surface = window_surface
+
+ egl_context = egl_display.create_context(egl_config)
+ assert egl_context.is_ok else print "Creating EGL context failed: {egl_display.error}"
+
+ var make_current_res = egl_display.make_current(window_surface, window_surface, egl_context)
+ assert make_current_res else print "Creating EGL make current failed: {egl_display.error}"
+
+ # TODO make the API selection configurable per platform
+ assert egl_bind_opengl_es_api else print "EGL bind API failed: {egl_display.error}"
+ end
+
+ redef fun width do return window_surface.attribs(egl_display).width
+
+ redef fun height do return window_surface.attribs(egl_display).height
+
+ # Close the EGL context
+ fun close_egl
+ do
+ egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none)
+ egl_display.destroy_context(egl_context)
+ egl_display.destroy_surface(window_surface)
+ end
+
+ redef fun flip
+ do
+ egl_display.swap_buffers(window_surface)
+ end
+end