Self-hosted OpenGL ES Development on ChromeOS?

Orange Pi Development Boards

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 ; )

Support CNX Software - Donate via PayPal or become a Patron on Patreon

7
Leave a Reply

avatar
2 Comment threads
5 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
NoloqoqbluWilliam Barath Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
William Barath
Guest

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
Guest
blu

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
Guest

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
Guest
blu

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.

blu
Guest
blu

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
Guest
Noloqoq

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
Guest
blu

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