For Developers‎ > ‎Design Documents‎ > ‎

Ozone Overview

Ozone is a platform abstraction layer beneath the Aura window system that is used for low level input and graphics. Once complete, the abstraction will support underlying systems ranging from embedded SoC targets to new X11-alternative window systems on Linux such as Wayland or Mir to bring up Aura Chromium by providing an implementation of the platform interface.

Guiding Principles

Our goal is to enable chromium to be used in a wide variety of projects by making porting to new platforms easy. To support this goal, ozone follows the following principles:
  1. Interfaces, not ifdefs. Differences between platforms are handled by calling a platform-supplied object through an interface instead of using conditional compilation. Platform internals remain encapsulated, and the public interface acts as a firewall between the platform-neutral upper layers (aura, blink, content, etc) and the platform-specific lower layers. The platform layer is relatively centralized to minimize the number of places ports need to add code.
  2. Flexible interfaces. The platform interfaces should encapsulate just what chrome needs from the platform, with minimal constraints on the platform's implementation as well as minimal constraints on usage from upper layers. An overly prescriptive interface is less useful for porting because fewer ports will be able to use it unmodified. Another way of stating is that the platform layer should provide mechanism, not policy.
  3. Runtime binding of platforms. Avoiding conditional compilation in the upper layers allows us to build multiple platforms into one binary and bind them at runtime. We allow this and provide a command-line flag to select a platform (--ozone-platform) if multiple are enabled. Each platform has a unique build define (e.g. ozone_platform_foo) that can be turned on or off independently.
  4. Easy out-of-tree platforms. Most ports begin as forks. Some of them later merge their code upstream, others will have an extended life out of tree. This is OK, and we should make this process easy to encourage ports, and to encourage frequent gardening of chromium changes into the downstream project. If gardening an out-of-tree port is hard, then those projects will simply ship outdated and potentially insecure chromium-derived code to users. One way we support these projects is by providing a way to inject additional platforms into the build without patching any gyp files.

Ozone Platform Interface

Ozone moves platform-specific code behind the following interfaces: 
  • PlatformWindow represents a window in the windowing system underlying chrome. Interaction with the windowing system (resize, maximize, close, etc) as well as dispatch of input events happens via this interface. Under aura, a PlatformWindow corresponds to a WindowTreeHost. Under mojo, it corresponds to a NativeViewport. On bare hardware, the underlying windowing system is very simple and a platform window corresponds to a physical display.
  • SurfaceFactoryOzone is used to create surfaces for the Chrome compositor to paint on using EGL/GLES2 or Skia.
  • GpuPlatformSupport & GpuPlatformSupportHost provide the platform code access to IPC between the browser & GPU processes. Some platforms need this to provide additional services in the GPU process such as display configuration.
  • CursorFactoryOzone is used to load & set platform cursors.
ChromeOS-specific interfaces
  • NativeDisplayDelegate is used on ChromeOS to support display configuration & hotplug.

Ozone in Chromium

Our implementation of Ozone required changes concentrated in these areas:
  • Cleaning up extensive assumptions about use of X11 throughout the tree, protecting this code behind the USE_X11 ifdef, and adding a new USE_OZONE path that works in a relatively platform-neutral way by delegating to the interfaces described above.
  • a WindowTreeHostOzone to send events into Aura and participate in display management on the host system, and
  • an Ozone-specific flavor of GLSurfaceEGL which delegates allocation of accelerated surfaces and refresh syncing to the provided implementation of SurfaceFactoryOzone.

Porting with Ozone

Users of the Ozone abstraction need to do the following, at minimum:
  • Write a subclass of PlatformWindow. This class (I'll call it PlatformWindowImpl) is responsible for window system integration. It can use MessagePumpLibevent to poll for events from file descriptors and then invoke PlatformWindowDelegate::DispatchEvent to dispatch each event.
  • Write a subclass of SurfaceFactoryOzone that handles allocating accelerated surfaces. I'll call this SurfaceFactoryOzoneImpl.
  • Write a subclass of CursorFactoryOzone to manage cursors, or use the BitmapCursorFactoryOzone implementation if only bitmap cursors need to be supported.
  • Write a subclass of OzonePlatform that owns instances of your SurfaceFactoryOzone and CursorFactoryOzone and provide a static constructor function for this object. This constructor will be called when your platform is selected and the returned object will be used to provide implementations of all the ozone platform interfaces.

Adding an Ozone Platform to the build (instructions for out-of-tree ports)

The recommended way to add your platform to the build is as follows. This walks through creating a new ozone platform called foo.
  1. Check out your code at src/ozone-foo.
  2. Create a file called src/ozone-foo/supplement.gypi with the following contents:
    { 'variables': { 'ozone_platform_foo%': 1, }, 'conditions': [ ['<(ozone_platform_foo) == 1', { 'variables': { 'external_ozone_platform_deps': [ '<(DEPTH)/ozone-foo/foo.gyp:foo', ], 'external_ozone_platforms': [ 'foo' ], 'ozone_platform%': 'foo', }, }], ], }
  3. Create a file called src/ozone-foo/foo.gyp with the following contents:
    { 'targets': [ { 'target_name': 'foo', 'type': 'static_library', 'dependencies': [ '<(DEPTH)/base/base.gyp:base', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', '<(DEPTH)/ui/events/events.gyp:events', # additional dependencies for your platform ], 'include_dirs': [ '..', ], 'sources': [ '', 'ozone_platform_foo.h', '', 'surface_factory_foo.h', '', 'event_factory_foo.h', # additional source files for your platform ], }, ] }
  4. Write a constructor function for your platform. It must be called ui::CreateOzonePlatformFoo. Put this function in the source file for your OzonePlatform subclass.
    OzonePlatform* CreateOzonePlatformFoo() { return new OzonePlatformFoo; }

Building with Ozone (ChromeOS - waterfall)

Building & running chrome (do this from the src directory):

GYP_DEFINES="use_ozone=1 chromeos=1" gclient runhooks
ninja -C out/Debug chrome
./out/Debug/chrome --disable-setuid-sandbox --ozone-platform=headless --ozone-dump-file=/tmp/chrome.png --ui-disable-threaded-compositing

Building with Ozone (Embedded - waterfall)

The following targets are currently working for embedded builds:
  • content_shell
  • various unit tests
The following targets are currently NOT supported:
  • ash_shell
  • chrome
    Building & running content_shell (do this from the src directory):

    GYP_DEFINES="embedded=1" gclient runhooks
    ninja -C out/Debug content_shell
    ./out/Debug/content_shell --disable-setuid-sandbox --ozone-platform=headless --ozone-dump-file=/tmp/content_shell.png --ui-disable-threaded-compositing

    Building with Ozone (Linux Desktop - bug)

    This is not supported by any of the in-tree platforms. Please see above and try a ChromeOS or embedded build for now.

    Note: The Ozone-wayland project has a desktop build for the wayland display protocol. See their project page for instructions.

    GYP Configuration notes:

    • You can turn properly implemented ozone platforms on and off with GYP_DEFINES. For example
      GYP_DEFINES="embedded=1 ozone_platform_gbm=0 ozone_platform_headless=0 ozone_platform_egltest=0"
      will turn off the current default platforms. This will result in a smaller binary and faster builds. To turn ALL platforms off by default, set ozone_auto_platforms=0.

    Running with Ozone

    Specify the platform you want to use at runtime using the --ozone-platform flag. Disabling the setuid sandbox may be required during development.

    For example, to run content_shell with the GBM platform:

    content_shell --disable-setuid-sandbox --ozone-platform=gbm

    If no platform is specified, the "test" platform is selected by default. This platform dumps images to a file and will not output to the screen. You can set the image path by specifying --ozone-dump-file=/path/to/image.png on the command line:

    content_shell --disable-setuid-sandbox --ozone-platform=headless --ozone-dump-file=/tmp/ozone.png


    • content_shell always runs at 800x600 resolution
    • For the GBM platform, you may need to terminate your X server (or any other display server) prior to testing.

    Ozone Platforms

    Internal platforms:
    • gbm - Linux direct rending with acceleration via mesa GBM & linux DRM/KMS (EGL/GLES2 accelerated rendering & modesetting in GPU process)
    • headless - Draws graphical output to a PNG image (no GPU support; software rendering only)
    • caca - Draws graphical output to text using libcaca (no GPU support; software rendering only). In case you ever wanted to test embedded content shell on tty. Add libcaca to your favourite Chromium development workstation and build like so:
    GYP_DEFINES="embedded=1 ozone_platform_caca=1" gclient runhooks
    ninja -C out/Debug content_shell
    out/Debug/content_shell --disable-setuid-sandbox --ozone-platform=caca 

    Note: traditional TTYs are not the ideal browsing experience.

    External platform projects:


    There is a public mailing list:

    Coming Soon

    The Ozone abstraction was first designed for the Ash window management approach where Chromium controls the entire display. This is not sufficient to fully support a foreign multi-window desktop.  We are currently working with contributors from Intel to generalize Ozone sufficiently so that it is adequate for DesktopAura-style Chromium ports such as a port of Aura Chromium to the Wayland platform.