SDL

Simple DirectMedia Layer (SDL) is an API for cross-platform low-level access to graphics, audio, and input hardware. The API is written in C, but bindings for various programming languages are available. The fortran-sdl2 library provides ISO C binding interfaces to SDL 2.0, allowing multimedia and game programming in Fortran (fig. 1).

Fortran voxel space
Fig. 1: Voxel space engine in Fortran, using SDL 2.0

Packages of SDL 2.0 are available for all Unix-like operating systems. On FreeBSD, simply run:

# pkg install audio/sdl2_mixer devel/sdl20 graphics/sdl2_image graphics/sdl2_ttf

On Linux, you may have to install additional development headers.

Example

The Fortran interfaces stay close to the binded C routines. We first have to initialise SDL, create a window, and, if we want hardware acceleration, create a renderer. In the main loop, events are polled and all the drawing occurs. When the application is terminated, we have to make sure the allocated memory is freed.

SDL2 Fortran
Fig. 2: Filling a yellow rectangle with SDL 2.0

This very basic example shows how to draw a coloured rectangle on the screen (fig. 2). Additional demo applications are part of the Fortran interface bindings.

! demo.f90
program main
    use, intrinsic :: iso_fortran_env, only: stdout => output_unit, stderr => error_unit
    use, intrinsic :: iso_c_binding, only: c_associated, c_null_char, c_ptr
    use :: sdl2
    implicit none

    integer, parameter :: SCREEN_WIDTH  = 640
    integer, parameter :: SCREEN_HEIGHT = 480

    type(c_ptr)     :: window
    type(c_ptr)     :: renderer
    type(sdl_event) :: event
    type(sdl_rect)  :: r
    integer         :: rc

    ! Initialise SDL.
    if (sdl_init(SDL_INIT_VIDEO) < 0) then
        write (stderr, *) 'SDL Error: ', sdl_get_error()
        stop
    end if

    ! Create the SDL window.
    window = sdl_create_window('SDL2 Fortran' // c_null_char, &
                               SDL_WINDOWPOS_UNDEFINED, &
                               SDL_WINDOWPOS_UNDEFINED, &
                               SCREEN_WIDTH, &
                               SCREEN_HEIGHT, &
                               SDL_WINDOW_SHOWN)

    if (.not. c_associated(window)) then
        write (stderr, *) 'SDL Error: ', sdl_get_error()
        stop
    end if

    ! Position and size of the rectangle.
    r = sdl_rect(50, 50, 150, 150)

    ! Create the renderer.
    renderer = sdl_create_renderer(window, -1, 0)

    ! Event loop.
    do
        ! Poll events.
        if (sdl_poll_event(event) > 0) then
            select case (event%type)
                case (SDL_QUITEVENT)
                    exit
            end select
        end if

        ! Fill screen black.
        rc = sdl_set_render_draw_color(renderer, &
                                       uint8(0), &
                                       uint8(0), &
                                       uint8(0), &
                                       uint8(SDL_ALPHA_OPAQUE))
        rc = sdl_render_clear(renderer)

        ! Fill the rectangle.
        rc = sdl_set_render_draw_color(renderer, &
                                       uint8(255), &
                                       uint8(255), &
                                       uint8(0), &
                                       uint8(SDL_ALPHA_OPAQUE))
        rc = sdl_render_fill_rect(renderer, r)

        ! Render to screen and wait 20 ms.
        call sdl_render_present(renderer)
        call sdl_delay(20)
    end do

    ! Quit gracefully.
    call sdl_destroy_renderer(renderer)
    call sdl_destroy_window(window)
    call sdl_quit()
end program main

First, compile the SDL 2 interface to object file sdl2.o. Then, compile and link the example program:

$ gfortran9 `sdl2-config --cflags` -o demo demo.f90 sdl2.o `sdl2-config --libs`
$ ./demo

References