Writing a driver of the DRI engine for your GPU.
Table of Contents
Overview
In order to support modern graphics card or GPU, we introduced a
new NEWGAL engine of dri
. The developer can use this engine to
run MiniGUI apps on a Linux box on which the DRI
(Direct Rendering Infrastructure) is enabled.
The dri
engine uses libdrm
developed by Free Desktop project:
https://dri.freedesktop.org/wiki/
Libdrm is a user-space library implements the Direct Rendering Manager. MiniGUI mainly uses this library to support the dumb frame buffer (no hardware acceleration). However, you can write a driver for your graphics card or GPU to implement the hardware accelerated features.
To avoid modifying the MiniGUI source code when supporting a new GPU,
the dri
engine has adopted a scalable design:
- You can directly use the
dri
engine to run MiniGUI on a GPU which supports dumb frame buffer. - When you want to take advantage of the hardware acceleration of
your GPU, you can write some code for your GPU as a sub driver
of
dri
engine outside MiniGUI.
This document describes how to enable dri
engine and write a
hardware-accelerated driver for your own GPU.
Note that, generally, the driver will be implemented by the GPU or SoC vendors. The MiniGUI app developers do not need to care about this.
Compile-time configuration
There are two configure options related to the dri
engine:
-
--enable-videodri
enables thedri
engine, and--disable-videodri
disables thedri
engine. Note that thedri
engine is only available on Linux, and you need to install thelibdrm
2.4 or later first. -
--with-targetname=external
. When you configure MiniGUI with this option, MiniGUI will use the external function__dri_ex_driver_get
to initialize the DRI driver. If you do not implement this function, the link will fail.
Run-time configuration
For dri
engine, we introduce a new section in MiniGUI runtime
configuration:
[dri]
defaultmode=1024x768-32bpp
dpi=96
pixelformat=XR24
device=/dev/dri/card0
Note that the defaultmode
and dpi
keys are standard keys for
a NEWGAL engine. These two keys define the screen resolution for
MiniGUI.
For dri
engine, you can use the key dri.device
to specify
your DRI device. Generally, it is /dev/dri/card0
.
You can use the key dri.pixelformat
to specify the DRM pixel format
of the screen. We use libdrm's fourcc code to defined the pixel format
of the screen surface in MiniGUI run-time configuration. For example,
XR24
means X8R8G8B8
pixel format, and AR32
means A8R8G8B8
pixel
format.
For more information, please see <drm/drm_fourcc.h>
header file.
Note that only 8/16/24/32 bpp RGB formats are supported.
Implement DRI driver
The header file <minigui/exstubs.h>
defines the external sutbs and
the driver operators (a set of callback functions) you need to implement
for your GPU externally.
First, you need to implement the following external stub:
DriDriverOps* __dri_ex_driver_get (const char* driver_name);
This function takes an argument driver_name
and returns NULL or
a valid pointer of DriDriverOps
to MiniGUI. The argument driver_name
gives the driver name determined by libdrm. Generally, it is the model
or number of your GPU. For example, for Intel i915 GPU, the driver name
will be i915
. The __dri_ex_driver_get
can returns different
DriDriverOps
to MiniGUI according to the driver name. In this way,
your implementation can support multiple GPUs.
If the external stub returns NULL, MiniGUI will use the dumb frame buffer instead.
The DriDriverOps
is a struct type consisted by a set of operators
(callbacks):
/**
* The struct type defines the operators for a DRI driver.
*/
typedef struct _DriDriverOps {
/**
* This operator creates the DriDriver object.
*
* \note The driver must implement this operator.
*/
DriDriver* (*create_driver) (int device_fd);
/**
* This operator destroies the DriDriver object.
*
* \note The driver must implement this operator.
*/
void (*destroy_driver) (DriDriver *driver);
/**
* This operator flushs the batch buffer of the driver or the hardware cache.
*
* \note This operator can be NULL.
*/
void (* flush_driver) (DriDriver *driver);
/**
* This operator creates a buffer with the specified pixel format,
* width, and height. If succeed, a valid (not zero) buffer identifier
* and the picth (row stride in bytes) will be returned.
* If failed, it returns 0.
*
* \note The driver must implement this operator.
*/
uint32_t (* create_buffer) (DriDriver *driver,
uint32_t drm_format,
unsigned int width, unsigned int height,
unsigned int *pitch);
BOOL (* fetch_buffer) (DriDriver *driver,
uint32_t buffer_id,
unsigned int *width, unsigned int *height,
unsigned int *pitch);
/**
* This operator maps the buffer into the current process's virtual memory
* space, and returns the virtual address. If failed, it returns NULL.
*
* \note The driver must implement this operator.
*/
DriSurfaceBuffer* (* map_buffer) (DriDriver *driver,
uint32_t buffer_id);
/**
* This operator un-maps a buffer.
*
* \note The driver must implement this operator.
*/
void (* unmap_buffer) (DriDriver *driver, DriSurfaceBuffer* buffer);
/**
* This operator destroies a buffer.
*
* \note The driver must implement this operator.
*/
void (* destroy_buffer) (DriDriver *driver, uint32_t buffer_id);
/**
* This operator clears the specific rectangle area of a buffer
* with the specific pixel value. If succeed, it returns 0.
*
* \note If this operator is set as NULL, the driver does not support
* hardware accelerated clear operation.
*/
int (* clear_buffer) (DriDriver *driver,
DriSurfaceBuffer* dst_buf, const GAL_Rect* rc, uint32_t pixel_value);
/**
* This operator checks whether a hardware accelerated blit
* can be done between the source buffer and the destination buffer.
* If succeed, it returns 0.
*
* \note If this operator is set as NULL, it will be supposed that
* the driver does not support any hardware accelerated blit operation.
*/
int (* check_blit) (DriDriver *driver,
DriSurfaceBuffer* src_buf, DriSurfaceBuffer* dst_buf);
/**
* This operator copies bits from a source buffer to a destination buffer.
*
* \note If this operator is set as NULL, the driver does not support
* hardware accelerated copy blit.
*/
int (* copy_blit) (DriDriver *driver,
DriSurfaceBuffer* src_buf, const GAL_Rect* src_rc,
DriSurfaceBuffer* dst_buf, const GAL_Rect* dst_rc,
enum DriColorLogicOp logic_op);
/**
* This operator blits pixles from a source buffer with the source alpha value
* specified to a destination buffer.
*
* \note If this operator is set as NULL, the driver does not support
* hardware accelerated blit with alpha.
*/
int (* alpha_blit) (DriDriver *driver,
DriSurfaceBuffer* src_buf, const GAL_Rect* src_rc,
DriSurfaceBuffer* dst_buf, const GAL_Rect* dst_rc, uint8_t alpha);
/**
* This operator blits pixles from a source buffer to a destination buffer,
* but skipping the pixel value specified by \a color_key.
*
* \note If this operator is set as NULL, the driver does not support
* hardware accelerated blit with color key.
*/
int (* key_blit) (DriDriver *driver,
DriSurfaceBuffer* src_buf, const GAL_Rect* src_rc,
DriSurfaceBuffer* dst_buf, const GAL_Rect* dst_rc, uint32_t color_key);
/**
* This operator blits pixles from a source buffer with the source alpha value
* specified to a destination buffer, but skipping the pixel value specified.
*
* \note If this operator is set as NULL, the driver does not support
* hardware accelerated blit with alpha and color key.
*/
int (* alpha_key_blit) (DriDriver *driver,
DriSurfaceBuffer* src_buf, const GAL_Rect* src_rc,
DriSurfaceBuffer* dst_buf, const GAL_Rect* dst_rc,
uint8_t alpha, uint32_t color_key);
} DriDriverOps;
If the external stub __dri_ex_driver_get
returns a valid pointer
of DriDriverOps
, MiniGUI will call the operator create_driver
to initialize the DRI driver. The operator will return a pointer
to the type of DriDriver
. All other operators of DriDriverOps
need this pointer as the context of your DRI driver.
Note that MiniGUI does not defined the detailed structure of
DriDriver
, it is up to your implementation:
/**
* The struct type represents the DRI sub driver.
* The concrete struct should be defined by the driver.
*/
struct _DriDriver;
typedef struct _DriDriver DriDriver;
For other operators, please see the comments above.
Restrictions
In version 4.0.0, the dri
NEWGAL engine does not provide support for
MiniGUI-Processes run-time mode. We will enhance this in the subsequent
version of MiniGUI.
Also note that when you use the hardware accelerated sub driver, MiniGUI app
may need the root privilege to call drmSetMaster
to set the video mode.
However, under MiniGUI-Processes run-time mode, only the server (mginit
) will
need this privilege when you use the future dri
engine.
Example
As an example, we implement the DRI driver for i915
graphics chard
in mg-tests/dri-engine/
. Please refer to mg-tests
repository:
https://github.com/VincentWei/mg-tests/tree/master/dri-engine
Future Features
In the near future, the MiniGUI team will:
- Enhance
dri
engine to support MiniGUI-Processes run-time mode. - Implement the MiniGUI back-end of
cairo
and MiniGUI EGL for OpenGL, OpenGL ES, and OpenVG, in order to fully exploit the GPU's 2D/3D accelerated rendering capabilities.
We will provide some samples in mg-tests
or mg-samples
for this purpose.