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 khronos.org 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:

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
Subscribe
Notify of
guest
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.
7 Comments
oldest
newest
William Barath
William Barath
6 years ago

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…

blu
blu
6 years ago

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.

William Barath
William Barath
6 years ago

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: https://www.reddit.com/r/linux/comments/5n0yc3/having_some_fun_with_wayland_support_in_chromeos/

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.

blu
blu
6 years ago

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… Read more »

blu
blu
6 years ago

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.

Noloqoq
Noloqoq
6 years ago

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.

blu
blu
6 years ago

Yes, PVR stands for PowerVR because on this chromebook the MT8173C hosts an ImgTech GX6250.

Boardcon Rockchip and Allwinner SoM and SBC products