This blog post refers to the public ARM Mali Midgard r6p0 user-space binary drivers for GNU/Linux which are now available for download. The "fbdev" variant now has support for dma-buf using a standard ioctl, which is explained in detail here.
The Linux kernel defines a user-space API that lets applications control displays via frame buffer drivers, also known as "fbdev" drivers. This is achieved via a set of file operations on "/dev/fb*" devices such as ioctl or mmap, which allows direct access to the pixel data of a display. While this is a simple, widespread, lightweight and powerful interface, it is no longer suitable in the world of modern embedded graphics computing.
For example, it does not provide any means to share the frame buffer directly with another kernel driver such as a GPU driver. When running an application that renders graphics with a GPU, each frame contains pixels that the GPU generated within its own buffers. The display controller is a separate entity with its own frame buffer located elsewhere in memory. So the standard way of displaying the GPU frames in fbdev mode is for the user-space (EGL part of the driver) to copy the data from a GPU buffer to the display controller's frame buffer. This is done on the CPU, typically by calling memcpy. This works, but can easily become the biggest bottleneck in the system and is therefore not acceptable in a real product.
There are many other limitations to "fbdev" which are not covered in this blog post, such as managing layers, synchronising applications with the display controller or performing 2D composition in hardware.
All new display controller drivers should be implementing the Direct Rendering Manager (DRM) API instead of fbdev. DRM offers a much more modern set of features and solves many of the problems seen with fbdev. However, there are still a lot of GPU-accelerated products that control their display using an fbdev Linux driver. Work needs to be done on each of these to avoid the unacceptably inefficient CPU memcpy and to let the GPU directly write into the frame buffer.
A typical way of achieving this is by using the dma-buf framework in the Linux kernel. Typically, the frame buffer driver registers itself as a dma-buf exporter and implements a way for user-space to get a file descriptor for this frame buffer (an ioctl). The user-space driver then passes the dma-buf file descriptor to the GPU kernel driver to import and use. When rendering happens, the GPU pixels are directly written into the frame buffer using a hardware DMA operation - this is also referred to as "zero-copy" and is much faster than calling memcpy. However, there is no standard ioctl in the fbdev API to export the frame buffer with dma-buf so each fbdev driver has a slightly different one. This means the user-space needs to be modified to work with each fbdev driver, which is not compatible with the public standard Mali binary drivers as they must not depend on platform specific display drivers.
This is why, starting with r6p0, we are adding a more generic ioctl implementation to export the dma-buf file descriptor defined as a custom extension to the standard fbdev API in supported kernels: the FBIOGET_DMABUF ioctl. This way, no extra dependency is being added on the user-space binary. If the ioctl is not available on a given kernel, then the user-space will revert to memcpy. We have already enabled this in our ODROID-XU3 Linux kernel branch on Github.
We should keep this added functionality in all our new fbdev Mali Midgard binary drivers and Linux kernels for supported platforms, such as ODROID-XU3, Chromebook devices with an ARM Mali GPU, Firefly.
[CTAToken URL = "https://developer.arm.com/products/software/mali-drivers/midgard-kernel" target="_blank" text="Mali Midgard GPU drivers" class ="green"]
First thanks to al of you solving the bottleneck, this is really great news!
Do I understand this article right that the new driver could support DRM?
Currently I'm trying to get Chrome / Ozone with the gdm platform running on an odroid-xu3.
So far it fails on creating the window surface.
mn on the binary blob shows that there is now a local eglCreatePlatformWindowSurfaceEXT imlementation in the r6p0 driver.
From definition this one should be used to pass an gdm surface instead of a native window, is it just a fake implementation?
Or is it somehow adressable using flags in eglCreateWindowSurface?
Thanks!