CastleWindow Backends

1. Introduction

TCastleWindowBase class represents a window suitable for Castle Game Engine rendering.

Most CGE applications use this class (although there is an alternative TCastleControlBase, but we advise TCastleWindowBase for most cases).

The TCastleWindowBase has a number of alternative backends, using different libraries underneath to manage the window and OpenGL(ES) context properties. By default, we use a backend that is considered "best" for the current operating system you’re compiling to, but you can override this choice by defining a symbol CASTLE_WINDOW_xxx at the compilation time. You can define this symbol in various places, e.g. in CastleEngineManifest.xml file.

Right now, we always use exactly one "backend", which is determined at the compile-time when you compile your application. In the future, we want to rework the CastleWindow infrastructure to enable you to use multiple backends, each backend in a separate unit, and (optionally) allow you to select the best backend at runtime.

2. Available backends

2.1. WinAPI backend (CASTLE_WINDOW_WINAPI)

The default backend on Windows. Looks native and supports everything.

Uses Windows API (WinAPI). By default it uses wgl to initialize OpenGL context. Can be also used (when symbol OpenGLES is defined) to initialize OpenGLES context using EGL. This way, you can test OpenGLES rendered on desktop Windows systems.

Supported platforms:

  • Windows only.

Advantages:

  • TCastleWindowBase.MainMenu is implemented as actual Windows menu bar, so it looks good and native.

  • Dialog windows like TCastleWindowBase.FileDialog are implemented using standard Windows dialog boxes, so again they look nice and native.

  • Supports both OpenGL (by wgl) and OpenGLES (by EGL) contexts.

2.2. GTK backend (CASTLE_WINDOW_GTK_2)

The default backend on most Unix systems, like Linux. Looks native and supports everything (except changing screen resolution, see below). Uses GTK 2. Initializes OpenGL(ES) context using Xlib + glX (for OpenGL) or EGL (for OpenGLES).

At some point, this will be also available under CASTLE_WINDOW_GTK symbol. At some further point, we will add backend CASTLE_WINDOW_GTK_3 and when it’s stable, CASTLE_WINDOW_GTK will be equivalent to CASTLE_WINDOW_GTK_3.

Supported platforms:

  • Works on any OS where GTK + glX / EGL works. Currently tested under Linux, FreeBSD, macOS.

Advantages:

  • TCastleWindowBase.MainMenu is implemented using GTK menu bar.

  • Dialog windows like TCastleWindowBase.FileDialog are implemented using GTK dialogs. So they look good and native.

  • Supports both OpenGL (by glX) and OpenGLES (by EGL) contexts.

Known problems:

  • Tab key cannot work as menu item shortcut (it’s always only for switching focus). This is an issue with GTK 2.

  • Application.TryVideoChange (to change screen resolution at runtime) is not finished, i.e. always returns false. See TODOs near CASTLE_WINDOW_USE_XF86VMODE definition.

History: at some point this was using GtkGlExt, and was portable to any system using GTK (even to Windows). This has changed because:

  • This way our dependencies are simpler (not every system has GtkGlExt),

  • there was not practical usage of this backend outside of GTK+Xlib anyway.

2.3. Xlib (X11) backend (CASTLE_WINDOW_XLIB)

A backend useful on most Unix systems, like Linux, that use X11.

Advantages compared to CASTLE_WINDOW_GTK (which supports similar platforms):

  • Doesn’t depend on GTK (one less dependency of your application).

  • Application.TryVideoChange works.

  • Supports both OpenGL (by glX) and OpenGLES (by EGL) contexts. By default it uses glX to initialize OpenGL context. But when symbol OpenGLES is defined, it uses EGL to initialize OpenGLES context. This way, you can test OpenGLES renderer on desktop Unix systems.

Known problems:

  • Doesn’t provide nicely-looking menu bar (TCastleWindowBase.MainMenu). Menu bar is not visible.

  • Doesn’t provide nicely-looking dialog boxes (TCastleWindowBase.FileDialog). The dialog boxes are implemented using simple modal boxes in CastleMessages instead, which works OK but doesn’t look pretty.

  • Full-screen (TCastleWindowBase.FullScreen) is realized using an obsolete method ("override_redirect") that doesn’t allow to switch applications with Alt+Tab from a fullscreen window.

2.4. Lazarus LCL backend (CASTLE_WINDOW_LCL)

Backend that uses Lazarus LCL to create a window. We use Lazarus TForm (with menu, dialogs and so on) and TOpenGLControl. This wraps Lazarus form and TOpenGLControl inside a TCastleWindowBase instance. In turn, Lazarus LCL may use various widgetsets, like GTK, Qt, WinAPI, Cocoa and others.

To use this:

  • Define CASTLE_WINDOW_LCL

  • Add castle_components package to the requirements of the castle_window Lazarus package.

    It will also automatically add LazOpenGLContext package as dependency, which is good. We need castle_components package for LCL helpers (like converting mouse/keys between LCL and CastleKeysMouse), and we need LazOpenGLContext package for TOpenGLControl.

  • Or you can use alternative_castle_window_based_on_lcl.lpk instead of castle_window.lpk in the project. This should take care of above 2 things.

  • Usually you should compile programs using Lazarus then (IDE or lazbuild), to automatically have correct LCL paths used. If you use our build tool or CGE editor, set build_using_lazbuild="true" in CastleEngineManifest.xml.

Supported platforms: everywhere where LCL runs. (But in practice this backend is only useful on macOS.)

Advantages:

  • Can use any LCL backend, in particular it allows to use Cocoa on macOS. This is the only way for now to have TCastleWindowBase have a native look on macOS. See CGE on macOS notes.

  • Depends on LCL for all the things, like TCastleWindowBase.MainMenu or TCastleWindowBase.FileDialog or TCastleWindowBase.FullScreen.

Known problems:

  • Various. Various small things don’t work perfectly using this backend, due to small problems/unfinished features in LCL. In practice, it isn’t really useful except on macOS, although it works on all platforms.

  • Screen resizing (Application.TryVideoChange) is not implemented, as LCL doesn’t implement it.

  • Message loop may stutter in case of a lot of mouse movement (may be visible in case of "mouse look" navigation).

  • Doesn’t support OpenGLES, as underlying TOpenGLControl doesn’t support it.

2.5. Android backend (CASTLE_WINDOW_ANDROID)

Backend using Android NDK cooperating with Castle Game Engine Android activity code. Used when you compile for Android, which you should always do using our build tool.

2.6. Library backend (CASTLE_WINDOW_LIBRARY)

Use existing OpenGL(ES) context. This is useful when the engine is used as a library, and an external code initializes OpenGL(ES) context, merely informing CGE about it. Useful for various cases, e.g. to "drive" Castle Game Engine rendering from another programming language. See examples/library/ for an example of wrapping CGE in a library.

Also, this is the only possible backend to use CGE on iOS or Nintendo Switch and it is automatically used there.

Supported platforms: All platforms. But note that using this backend requires additional "outside" code to manage our library. In case of iOS and Nintendo Switch, this is automatically provided when building using our build tool.

2.7. Template (CASTLE_WINDOW_TEMPLATE)

A dummy backend that does nothing, but compiles. Can be used as a starting point when developing new CastleWindow backends.

Supported platforms: All platforms.

3. Making new backend

  • Invent a symbol CASTLE_WINDOW_FOO for a new backend, document it in the "available backends list" above.

  • Create a file castlewindow_foo.inc with contents from castlewindow_backend_template.inc and conditionally include it from castlewindow_backend.inc.

  • Adjust defining CASTLE_WINDOW_HAS_VIDEO_CHANGE and CASTLE_WINDOW_USE_PRIVATE_MODIFIERS_DOWN for your backend.

  • Implement all methods in castlewindow_foo.inc.

  • Call TCastleWindowBase.DoXxx functions at appropriate places from your backend. You can call all DoUpdate and DoTimer for all Application.OpenWindows using Application.FOpenWindows.DoUpdate/Timer.

  • Call TCastleApplication.DoApplicationUpdate and DoApplicationTimer when appropriate. Remember that you can always assume that the ONLY existing instance of TCastleApplication is Application.

  • Remember that probably you will have to call ReleaseAllKeysAndMouse when user switches to another window or activates MainMenu.


To improve this documentation just edit the source of this page in AsciiDoctor (simple wiki-like syntax) and create a pull request to Castle Game Engine WWW (cge-www) repository.