Self-hosted OpenGL ES Development on ChromeOS?

This is a guest post by blu about developing OpenGL ES applications on Chrome OS.

Ever since I’ve been using a chromebook in developer mode as my daily notebook (can’t beat 10h-plus battery life on ~300EUR well-performing machines), I’ve been missing one thing ‒ OpenGL ES coding under ChromeOS.

My chromebook is more than well-equipped for GLES3 hardware-wise (verified via dual-booting to ArchLinux), and I always have up-to-date toolchains self-hosted under ChromeOS, thanks to an excellent package manager aptly named Chromebrew. And yet my coding-on-the-go under ChromeOS has been limited to console apps ‒ ChromeOS has strict limitations which include no X11 display manager, or any other industry-standard display manager that I’m aware of, and I don’t feel like dual-booting into ArchLinux too often ‒ ChromeOS has spoiled me with its fine-tuned performance. The no-display-manager limitation of ChromeOS is usually worked-around via Crouton but in my case Crouton would not help ‒ no 3D-hardware-accelerated support on ARM chromebooks. So in anticipation of Project Crostini landing on my Chromebook, I’ve decided to give ChromeOS ‘stock’ developer mode a self-hosted OpenGLES quick-n-dirty try.

A disclaimer before we start: ChromeOS does support Android apps as well as native apps in the browser in the form of PNaCl Native Modules ‒ natively-built sandboxed binaries, akin to ActiveX in the Internet Explorer of yesteryears.

Unfortunately there’s one problem with that ‒ you can’t code PNaCl apps natively on an Arm chromebook ‒ the SDK toolchain was not meant to work on armhf userspaces. And frankly, I’m not keen on PNaCl so I’d rather leave hacking armhf support into that as a last resort. So what are the other options for self-hosted OGL ES development?

A quick check under /usr/lib shows the presence of libdrm, libGLESv2 and libEGL ‒ basic prerequisites met! We need to find matching headers for the latter two of these libraries as we directly interact with them. Luckily, industry-standard APIs like EGL and GLESv2 guarantee backward compatibility, so we don’t need to precisely match the libraries versions, as long as we target older-or-same-version functionality. So let’s head over to and grab the headers for EGL 1.4 and GLES2 respectively.

First attempt to build basic EGL + GLES2 code under ChromeOS results in header EGL/eglplarform.h seeking to include X11 header Xlib.h ‒ bad move. Let’s patch that into something sensible for an X11-less unix:

Our simple code builds now! Here’s a glance at the link dependencies ‒ everything originating from /usr/local/lib was provided by Chromebrew packages:

But does the so-built code run to a satisfactory result?

From using EGL under ArchLinux on my Chromebook I know that one can request a ‘null-window’ drawing surface from ImgTech’s EGL stack (a version of which is used in ChromeOS as well), which produces a straight-forward full-screen output. Trying the same approach under ChromeOS fails at eglCreateWindowSurface() with a EGL_BAD_NATIVE_WINDOW run-time error ‒ oh well. At least that surface creation happens after we have already initialized a functioning EGL stack, so we could still check for useful bits of EGL info. A quick query for valid renderable configurations reveals that our EGL stack offers a bunch of configurations, so let’s pick one for our further experiments. We’ll just go with the first available ‒ EGL_CONFIG_ID 0x1 ‒ it does not have a z-buffer or stencil attachments, but appears to be an otherwise perfectly-good native-renderable config (config attributes listed):

With our optimistic ‘null-window’ surface approach failing with a run-time error, we have a simple option left ‒ off-screen rendering. So let’s change our original EGL API call requesting a ‘null-window’ surface into one requesting a PBuffer-based surface:

Clearly, we won’t be showing anything on screen, given we transitioned from a full-screen ‘null-window’ surface to an off-screen pbuffer, but hey, we will know if we can render!

Running our simple code with the above off-screen patch (passing a bunch of CLI params among which specifying EGL config_id 1 for a renderable, requesting 1000 frames of rendering, recording the last frame to a png and specifying screen geometry of 1Kx1K at a fictitious 60Hz) produces:

So we crashed the PVR GLES stack at teardown, but hey, our framegrab contains a perfectly valid tangent-space bump-mapped stone sphere, and the framerate results should be valid as well!

opengl ES chromeos

Not bad for 15 lines of patches over code never meant to build and run on ChromeOS. Next time I’ll try to figure out how to display rendering at run-time, if Project Crostini is not released soon, that is ; )

Share this:
FacebookTwitterHacker NewsSlashdotRedditLinkedInPinterestFlipboardMeWeLineEmailShare

Support CNX Software! Donate via cryptocurrencies, become a Patron on Patreon, or purchase goods on Amazon or Aliexpress

ROCK 5 ITX RK3588 mini-ITX motherboard

Radxa ROCK 5C (Lite) SBC with Rockchip RK3588 / RK3582 SoC

7 Replies to “Self-hosted OpenGL ES Development on ChromeOS?”

  1. There are wayland libraries for chromebrew… maybe you’ll find some joy there.

    Another option would be to use libffi to open chrome itself and use it as a rendering library… hook anywhere from WebGL to the desktop compositor…

    1. Thanks for the wayland heads-up — it never occurred to me to check for a wayland lib in chromebrew : /

      Re libffi — it looks really useful, but I’ll try first to get things running for C/C++ — I’ve been thinking going the opposite direction from the browser — to the DRM ioctls.

      1. DRM is really complex. You’ll be able to skip a lot of that complexity by relying on a lot of assumptions about how ChromeOS has already set things up, but that won’t make your code very portable. libSDL via the wayland surface seems like the path of least resistance while still being portable.

        I just found this:

        So it looks like Google has brought in more standard wayland features as a result of adding support for running android apps. It shows Weston, a couple Gnome apps, and neverputt running.

        1. So I just gave wayland a shot on chromeOS — what you say is true, wayland generally works, alas..

          It appears all renderable configs provided by ChromeOS EGL are either of EGL_SURFACE_TYPE pbuffer (what I used in the test), or EGL_SURFACE_TYPE 0x0 which is an invalid surface-type mask. Ergo, all attempts to create an EGL surface from a native window (obtained via wl_egl_window_create()) fail with fail with an error EGL_BAD_NATIVE_WINDOW just because there are no matching renderable configs to pass along with the wl_egl_window. Basically a catch 22 situation WRT creating a window-able EGL surface. The alternative is to manually (i.e. CPU) blit the pbuffer to a wl_surface, which is a very lame solution. So close yet so far.. Oh well.

        2. To correct one factual error in the article — the EGL under ChromeOS is not ImgTech’s but Mesa’s, as can be seen in the diagnostic logs I collect, but apparently don’t read : / The GLESv2 stack is ImgTech’s, which mislead me to see things which were not there.

  2. there is a bug on the link to Crostini.

    I’m not sure to understand if PVR is really about PowerVR. There are ChromeBook with different chips including Rockchips that include ARM Mali, that now have (still in active development drivers), Lima for Mali~400 and Panfrost for other series, that can run on Full Linux (not crouton/crostini) now. Anyway thanks for these information, it will be helpful in several cases.

Leave a Reply

Your email address will not be published. Required fields are marked *

Khadas VIM4 SBC
Khadas VIM4 SBC