
<!-- I release these notes into the public domain -->

# Platform Support Library (`platform`)

## Table of Contents

<!-- TOC -->
* [Home](./CONTENTS.md#planning-documentation-for-fennec)
* [Platform Support Library (`platform`)](#platform-support-library-platform)
  * [Table of Contents](#table-of-contents)
  * [Introduction](#introduction)
  * [Implementation](#implementation)
  * [Consoles](#consoles)
<!-- TOC -->


## Introduction

&ensp; The platform support library will include headers, functions, and classes related
to supporting various platforms. Platforms may be defined as any Hardware, OS, or
Drivers that must be initialized for the engine context.


## Changes

&ensp; For the foreseeable future, I will be switching to SDL for window management.
SDL was chosen over GLFW due to GLFW's lack of support for Android and iOS. A custom
implementation is still something I would like to do, but is currently out of scope for
where I would like to focus my energy. As soon as SDL becomes 


## Implementation

Platform Support will be implemented in the following order:
- Linux/BSD
    - Wayland
        - OpenGL (EGL) ✅
        - XKB
        - PulseAudio
        - Vulkan
    - X11
        - ALSA
        - Vulkan
- Microsoft Windows
    - XInput
    - OpenGL (WGL)
    - WASAPI
    - Vulkan
- Android
    - OpenGL ES
    - AAudio
    - openslES
- macOS/iOS
    - cocoa
        - OpenGL
        - Core Audio
        - Vulkan
        - Metal

&ensp; Linux Wayland will be implemented first. Once setup, the core engine will be 
implemented and tested on top of Wayland. Once the engine is in a stable state,
then support for other platforms will be resumed.


## Consoles

&ensp; Most consoles will never get official platform support due to NDAs which conflict
with the principles of this engine. fennec will avoid using proprietary libraries except
when strictly necessary, such as support for Windows and MacOS. fennec will interact
with any drivers required for the listed operating systems above, even if proprietary.

## Notes

We want this system to be fairly modular, renderers and their respective
gfxcontext implementation should be a drop-in, as well as window implementation.
This is a fairly complex problem to solve, especially since most display protocols
have their own specific implementation for supporting different contexts.

To illustrate this problem, let's say we have SDL and OpenGL implemented.

If we were to add Vulkan, there are Vulkan specific functions
for creating a window compatible with SDL, i.e. SDL_Vulkan_CreateSurface.
Who should know how to implement this function? How do we define the API
so that we do not have to modify existing classes to add Vulkan support?

The easiest solution to this problem is template functions. We can have a
template that takes a Renderer type as a template parameter, then initialize
the window for that. Now, if someone wants to create a Vulkan renderer, all they
have to do is write an overload for the template function. This can be neatly
wrapped up in a single C++ file. Only the gfxcontext implementation has to know
of this function's existence since it will be the one calling the function.

The main drawback with this implementation is an outside observer calling the
template function directly. Only the one C++ file knows of its existence. Template
functions are inlined after all. There are two options to solve this, the ``[[noinline]]``
attribute, or we simply scope protect the function and create it purely from a
"driver" standpoint. We can register drivers with the platform, then retrieve a
list of drivers with a specific type, e.g. glcontext, then the type aware implementation
is isolated to the C++ file associated with glcontext, and glcontext registers
itself with the platform. We can give drivers a priority so that Vulkan, a more
modern and "more powerful" renderer is chosen first, if available, and falls back
to OpenGL.

Now we run into the issue of, what if we want to implement Vulkan and Wayland separately?
These implementations will be part of the core engine, but let's take a more contrived
example; X-Box and Playstation. X-Box and Playstation have their own protocols for
display rendering, but both use DirectX. Say someone implements a DirectX api for Desktop
computers, then someone else implements a windowing system for X-Box or Playstation. 
If another user wants to use DirectX with X-Box/Playstation, they will have to write
their own overloads for that implementation.

The only viable solution for this problem is to rely on the Open Source community.
Pray that someone finds both engine extensions and writes the overloads for you.
This might sound very familiar to modders, and this is my intention with this engine.
Pieces should be modular, and should be easily connected when two non-dependent systems
have underlying interdependencies.

There is one more option that I have come up with; mapping type ids. The implementation
of typed.h generates type ids *at runtime* which allows us to map a pair of ids for this
purpose. We can use a pair of window and gfxcontext uuids to determine the loading functions.
All we would need to do is register a function that takes a window as an arguments and 
constructs the gfxcontext. We can combine this with the above to allow scoped access to 
the classes if that is needed.
