summaryrefslogtreecommitdiffstats
path: root/man
diff options
context:
space:
mode:
Diffstat (limited to 'man')
-rw-r--r--man/drm-kms.7.rst229
-rw-r--r--man/drm-memory.7.rst313
-rw-r--r--man/drm.7.rst91
-rw-r--r--man/drmAvailable.3.rst41
-rw-r--r--man/drmHandleEvent.3.rst62
-rw-r--r--man/drmModeGetResources.3.rst92
-rw-r--r--man/meson.build40
7 files changed, 868 insertions, 0 deletions
diff --git a/man/drm-kms.7.rst b/man/drm-kms.7.rst
new file mode 100644
index 0000000..587d7eb
--- /dev/null
+++ b/man/drm-kms.7.rst
@@ -0,0 +1,229 @@
+=======
+drm-kms
+=======
+
+-------------------
+Kernel Mode-Setting
+-------------------
+
+:Date: September 2012
+:Manual section: 7
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+``#include <xf86drmMode.h>``
+
+Description
+===========
+
+Each DRM device provides access to manage which monitors and displays are
+currently used and what frames to be displayed. This task is called *Kernel
+Mode-Setting* (KMS). Historically, this was done in user-space and called
+*User-space Mode-Setting* (UMS). Almost all open-source drivers now provide the
+KMS kernel API to do this in the kernel, however, many non-open-source binary
+drivers from different vendors still do not support this. You can use
+**drmModeSettingSupported**\ (3) to check whether your driver supports this. To
+understand how KMS works, we need to introduce 5 objects: *CRTCs*, *Planes*,
+*Encoders*, *Connectors* and *Framebuffers*.
+
+CRTCs
+ A *CRTC* short for *CRT Controller* is an abstraction representing a part of
+ the chip that contains a pointer to a scanout buffer. Therefore, the number
+ of CRTCs available determines how many independent scanout buffers can be
+ active at any given time. The CRTC structure contains several fields to
+ support this: a pointer to some video memory (abstracted as a frame-buffer
+ object), a list of driven connectors, a display mode and an (x, y) offset
+ into the video memory to support panning or configurations where one piece
+ of video memory spans multiple CRTCs. A CRTC is the central point where
+ configuration of displays happens. You select which objects to use, which
+ modes and which parameters and then configure each CRTC via
+ **drmModeCrtcSet**\ (3) to drive the display devices.
+
+Planes
+ A *plane* respresents an image source that can be blended with or overlayed
+ on top of a CRTC during the scanout process. Planes are associated with a
+ frame-buffer to crop a portion of the image memory (source) and optionally
+ scale it to a destination size. The result is then blended with or overlayed
+ on top of a CRTC. Planes are not provided by all hardware and the number of
+ available planes is limited. If planes are not available or if not enough
+ planes are available, the user should fall back to normal software blending
+ (via GPU or CPU).
+
+Encoders
+ An *encoder* takes pixel data from a CRTC and converts it to a format
+ suitable for any attached connectors. On some devices, it may be possible to
+ have a CRTC send data to more than one encoder. In that case, both encoders
+ would receive data from the same scanout buffer, resulting in a *cloned*
+ display configuration across the connectors attached to each encoder.
+
+Connectors
+ A *connector* is the final destination of pixel-data on a device, and
+ usually connects directly to an external display device like a monitor or
+ laptop panel. A connector can only be attached to one encoder at a time. The
+ connector is also the structure where information about the attached display
+ is kept, so it contains fields for display data, *EDID* data, *DPMS* and
+ *connection status*, and information about modes supported on the attached
+ displays.
+
+Framebuffers
+ *Framebuffers* are abstract memory objects that provide a source of pixel
+ data to scanout to a CRTC. Applications explicitly request the creation of
+ framebuffers and can control their behavior. Framebuffers rely on the
+ underneath memory manager for low-level memory operations. When creating a
+ framebuffer, applications pass a memory handle through the API which is used
+ as backing storage. The framebuffer itself is only an abstract object with
+ no data. It just refers to memory buffers that must be created with the
+ **drm-memory**\ (7) API.
+
+Mode-Setting
+------------
+
+Before mode-setting can be performed, an application needs to call
+**drmSetMaster**\ (3) to become *DRM-Master*. It then has exclusive access to
+the KMS API. A call to **drmModeGetResources**\ (3) returns a list of *CRTCs*,
+*Connectors*, *Encoders* and *Planes*.
+
+Normal procedure now includes: First, you select which connectors you want to
+use. Users are mostly interested in which monitor or display-panel is active so
+you need to make sure to arrange them in the correct logical order and select
+the correct ones to use. For each connector, you need to find a CRTC to drive
+this connector. If you want to clone output to two or more connectors, you may
+use a single CRTC for all cloned connectors (if the hardware supports this). To
+find a suitable CRTC, you need to iterate over the list of encoders that are
+available for each connector. Each encoder contains a list of CRTCs that it can
+work with and you simply select one of these CRTCs. If you later program the
+CRTC to control a connector, it automatically selects the best encoder.
+However, this procedure is needed so your CRTC has at least one working encoder
+for the selected connector. See the *Examples* section below for more
+information.
+
+All valid modes for a connector can be retrieved with a call to
+**drmModeGetConnector**\ (3) You need to select the mode you want to use and save it.
+The first mode in the list is the default mode with the highest resolution
+possible and often a suitable choice.
+
+After you have a working connector+CRTC+mode combination, you need to create a
+framebuffer that is used for scanout. Memory buffer allocation is
+driver-dependent and described in **drm-memory**\ (7). You need to create a
+buffer big enough for your selected mode. Now you can create a framebuffer
+object that uses your memory-buffer as scanout buffer. You can do this with
+**drmModeAddFB**\ (3) and **drmModeAddFB2**\ (3).
+
+As a last step, you want to program your CRTC to drive your selected connector.
+You can do this with a call to **drmModeSetCrtc**\ (3).
+
+Page-Flipping
+-------------
+
+A call to **drmModeSetCrtc**\ (3) is executed immediately and forces the CRTC
+to use the new scanout buffer. If you want smooth-transitions without tearing,
+you probably use double-buffering. You need to create one framebuffer object
+for each buffer you use. You can then call **drmModeSetCrtc**\ (3) on the next
+buffer to flip. If you want to synchronize your flips with *vertical-blanks*,
+you can use **drmModePageFlip**\ (3) which schedules your page-flip for the
+next *vblank*.
+
+Planes
+------
+
+Planes are controlled independently from CRTCs. That is, a call to
+**drmModeSetCrtc**\ (3) does not affect planes. Instead, you need to call
+**drmModeSetPlane**\ (3) to configure a plane. This requires the plane ID, a
+CRTC, a framebuffer and offsets into the plane-framebuffer and the
+CRTC-framebuffer. The CRTC then blends the content from the plane over the CRTC
+framebuffer buffer during scanout. As this does not involve any
+software-blending, it is way faster than traditional blending. However, plane
+resources are limited. See **drmModeGetPlaneResources**\ (3) for more
+information.
+
+Cursors
+-------
+
+Similar to planes, many hardware also supports cursors. A cursor is a very
+small buffer with an image that is blended over the CRTC framebuffer. You can
+set a different cursor for each CRTC with **drmModeSetCursor**\ (3) and move it
+on the screen with **drmModeMoveCursor**\ (3). This allows to move the cursor
+on the screen without rerendering. If no hardware cursors are supported, you
+need to rerender for each frame the cursor is moved.
+
+Examples
+========
+
+Some examples of how basic mode-setting can be done. See the man-page of each
+DRM function for more information.
+
+CRTC/Encoder Selection
+----------------------
+
+If you retrieved all display configuration information via
+**drmModeGetResources**\ (3) as ``drmModeRes *res``, selected a connector from
+the list in ``res->connectors`` and retrieved the connector-information as
+``drmModeConnector *conn`` via **drmModeGetConnector**\ (3) then this example
+shows, how you can find a suitable CRTC id to drive this connector. This
+function takes a file-descriptor to the DRM device (see **drmOpen**\ (3)) as
+``fd``, a pointer to the retrieved resources as ``res`` and a pointer to the
+selected connector as ``conn``. It returns an integer smaller than 0 on
+failure, otherwise, a valid CRTC id is returned.
+
+::
+
+ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn)
+ {
+ drmModeEncoder *enc;
+ unsigned int i, j;
+
+ /* iterate all encoders of this connector */
+ for (i = 0; i < conn->count_encoders; ++i) {
+ enc = drmModeGetEncoder(fd, conn->encoders[i]);
+ if (!enc) {
+ /* cannot retrieve encoder, ignoring... */
+ continue;
+ }
+
+ /* iterate all global CRTCs */
+ for (j = 0; j < res->count_crtcs; ++j) {
+ /* check whether this CRTC works with the encoder */
+ if (!(enc->possible_crtcs & (1 << j)))
+ continue;
+
+
+ /* Here you need to check that no other connector
+ * currently uses the CRTC with id "crtc". If you intend
+ * to drive one connector only, then you can skip this
+ * step. Otherwise, simply scan your list of configured
+ * connectors and CRTCs whether this CRTC is already
+ * used. If it is, then simply continue the search here. */
+ if (res->crtcs[j] "is unused") {
+ drmModeFreeEncoder(enc);
+ return res->crtcs[j];
+ }
+ }
+
+ drmModeFreeEncoder(enc);
+ }
+
+ /* cannot find a suitable CRTC */
+ return -ENOENT;
+ }
+
+Reporting Bugs
+==============
+
+Bugs in this manual should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues
+
+See Also
+========
+
+**drm**\ (7), **drm-memory**\ (7), **drmModeGetResources**\ (3),
+**drmModeGetConnector**\ (3), **drmModeGetEncoder**\ (3),
+**drmModeGetCrtc**\ (3), **drmModeSetCrtc**\ (3), **drmModeGetFB**\ (3),
+**drmModeAddFB**\ (3), **drmModeAddFB2**\ (3), **drmModeRmFB**\ (3),
+**drmModePageFlip**\ (3), **drmModeGetPlaneResources**\ (3),
+**drmModeGetPlane**\ (3), **drmModeSetPlane**\ (3), **drmModeSetCursor**\ (3),
+**drmModeMoveCursor**\ (3), **drmSetMaster**\ (3), **drmAvailable**\ (3),
+**drmCheckModesettingSupported**\ (3), **drmOpen**\ (3)
diff --git a/man/drm-memory.7.rst b/man/drm-memory.7.rst
new file mode 100644
index 0000000..7d09eeb
--- /dev/null
+++ b/man/drm-memory.7.rst
@@ -0,0 +1,313 @@
+==========
+drm-memory
+==========
+
+---------------------
+DRM Memory Management
+---------------------
+
+:Date: September 2012
+:Manual section: 7
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+Description
+===========
+
+Many modern high-end GPUs come with their own memory managers. They even
+include several different caches that need to be synchronized during access.
+Textures, framebuffers, command buffers and more need to be stored in memory
+that can be accessed quickly by the GPU. Therefore, memory management on GPUs
+is highly driver- and hardware-dependent.
+
+However, there are several frameworks in the kernel that are used by more than
+one driver. These can be used for trivial mode-setting without requiring
+driver-dependent code. But for hardware-accelerated rendering you need to read
+the manual pages for the driver you want to work with.
+
+Dumb-Buffers
+------------
+
+Almost all in-kernel DRM hardware drivers support an API called *Dumb-Buffers*.
+This API allows to create buffers of arbitrary size that can be used for
+scanout. These buffers can be memory mapped via **mmap**\ (2) so you can render
+into them on the CPU. However, GPU access to these buffers is often not
+possible. Therefore, they are fine for simple tasks but not suitable for
+complex compositions and renderings.
+
+The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl can be used to create a dumb buffer.
+The kernel will return a 32-bit handle that can be used to manage the buffer
+with the DRM API. You can create framebuffers with **drmModeAddFB**\ (3) and
+use it for mode-setting and scanout. To access the buffer, you first need to
+retrieve the offset of the buffer. The ``DRM_IOCTL_MODE_MAP_DUMB`` ioctl
+requests the DRM subsystem to prepare the buffer for memory-mapping and returns
+a fake-offset that can be used with **mmap**\ (2).
+
+The ``DRM_IOCTL_MODE_CREATE_DUMB`` ioctl takes as argument a structure of type
+``struct drm_mode_create_dumb``:
+
+::
+
+ struct drm_mode_create_dumb {
+ __u32 height;
+ __u32 width;
+ __u32 bpp;
+ __u32 flags;
+
+ __u32 handle;
+ __u32 pitch;
+ __u64 size;
+ };
+
+The fields *height*, *width*, *bpp* and *flags* have to be provided by the
+caller. The other fields are filled by the kernel with the return values.
+*height* and *width* are the dimensions of the rectangular buffer that is
+created. *bpp* is the number of bits-per-pixel and must be a multiple of 8. You
+most commonly want to pass 32 here. The flags field is currently unused and
+must be zeroed. Different flags to modify the behavior may be added in the
+future. After calling the ioctl, the handle, pitch and size fields are filled
+by the kernel. *handle* is a 32-bit gem handle that identifies the buffer. This
+is used by several other calls that take a gem-handle or memory-buffer as
+argument. The *pitch* field is the pitch (or stride) of the new buffer. Most
+drivers use 32-bit or 64-bit aligned stride-values. The size field contains the
+absolute size in bytes of the buffer. This can normally also be computed with
+``(height * pitch + width) * bpp / 4``.
+
+To prepare the buffer for **mmap**\ (2) you need to use the
+``DRM_IOCTL_MODE_MAP_DUMB`` ioctl. It takes as argument a structure of type
+``struct drm_mode_map_dumb``:
+
+::
+
+ struct drm_mode_map_dumb {
+ __u32 handle;
+ __u32 pad;
+
+ __u64 offset;
+ };
+
+You need to put the gem-handle that was previously retrieved via
+``DRM_IOCTL_MODE_CREATE_DUMB`` into the *handle* field. The *pad* field is
+unused padding and must be zeroed. After completion, the *offset* field will
+contain an offset that can be used with **mmap**\ (2) on the DRM
+file-descriptor.
+
+If you don't need your dumb-buffer, anymore, you have to destroy it with
+``DRM_IOCTL_MODE_DESTROY_DUMB``. If you close the DRM file-descriptor, all open
+dumb-buffers are automatically destroyed. This ioctl takes as argument a
+structure of type ``struct drm_mode_destroy_dumb``:
+
+::
+
+ struct drm_mode_destroy_dumb {
+ __u32 handle;
+ };
+
+You only need to put your handle into the *handle* field. After this call, the
+handle is invalid and may be reused for new buffers by the dumb-API.
+
+TTM
+---
+
+*TTM* stands for *Translation Table Manager* and is a generic memory-manager
+provided by the kernel. It does not provide a common user-space API so you need
+to look at each driver interface if you want to use it. See for instance the
+radeon man pages for more information on memory-management with radeon and TTM.
+
+GEM
+---
+
+*GEM* stands for *Graphics Execution Manager* and is a generic DRM
+memory-management framework in the kernel, that is used by many different
+drivers. GEM is designed to manage graphics memory, control access to the
+graphics device execution context and handle essentially NUMA environment
+unique to modern graphics hardware. GEM allows multiple applications to share
+graphics device resources without the need to constantly reload the entire
+graphics card. Data may be shared between multiple applications with gem
+ensuring that the correct memory synchronization occurs.
+
+GEM provides simple mechanisms to manage graphics data and control execution
+flow within the linux DRM subsystem. However, GEM is not a complete framework
+that is fully driver independent. Instead, if provides many functions that are
+shared between many drivers, but each driver has to implement most of
+memory-management with driver-dependent ioctls. This manpage tries to describe
+the semantics (and if it applies, the syntax) that is shared between all
+drivers that use GEM.
+
+All GEM APIs are defined as **ioctl**\ (2) on the DRM file descriptor. An
+application must be authorized via **drmAuthMagic**\ (3) to the current
+DRM-Master to access the GEM subsystem. A driver that does not support GEM will
+return ``ENODEV`` for all these ioctls. Invalid object handles return
+``EINVAL`` and invalid object names return ``ENOENT``.
+
+Gem provides explicit memory management primitives. System pages are allocated
+when the object is created, either as the fundamental storage for hardware
+where system memory is used by the graphics processor directly, or as backing
+store for graphics-processor resident memory.
+
+Objects are referenced from user-space using handles. These are, for all
+intents and purposes, equivalent to file descriptors but avoid the overhead.
+Newer kernel drivers also support the **drm-prime** (7) infrastructure which
+can return real file-descriptor for GEM-handles using the linux DMA-BUF API.
+Objects may be published with a name so that other applications and processes
+can access them. The name remains valid as long as the object exists.
+GEM-objects are reference counted in the kernel. The object is only destroyed
+when all handles from user-space were closed.
+
+GEM-buffers cannot be created with a generic API. Each driver provides its own
+API to create GEM-buffers. See for example ``DRM_I915_GEM_CREATE``,
+``DRM_NOUVEAU_GEM_NEW`` or ``DRM_RADEON_GEM_CREATE``. Each of these ioctls
+returns a GEM-handle that can be passed to different generic ioctls. The
+*libgbm* library from the *mesa3D* distribution tries to provide a
+driver-independent API to create GBM buffers and retrieve a GBM-handle to them.
+It allows to create buffers for different use-cases including scanout,
+rendering, cursors and CPU-access. See the libgbm library for more information
+or look at the driver-dependent man-pages (for example **drm-intel**\ (7) or
+**drm-radeon**\ (7)).
+
+GEM-buffers can be closed with **drmCloseBufferHandle**\ (3). It takes as
+argument the GEM-handle to be closed. After this call the GEM handle cannot be
+used by this process anymore and may be reused for new GEM objects by the GEM
+API.
+
+If you want to share GEM-objects between different processes, you can create a
+name for them and pass this name to other processes which can then open this
+GEM-object. Names are currently 32-bit integer IDs and have no special
+protection. That is, if you put a name on your GEM-object, every other client
+that has access to the DRM device and is authenticated via
+**drmAuthMagic**\ (3) to the current DRM-Master, can *guess* the name and open
+or access the GEM-object. If you want more fine-grained access control, you can
+use the new **drm-prime**\ (7) API to retrieve file-descriptors for
+GEM-handles. To create a name for a GEM-handle, you use the
+``DRM_IOCTL_GEM_FLINK`` ioctl. It takes as argument a structure of type
+``struct drm_gem_flink``:
+
+::
+
+ struct drm_gem_flink {
+ __u32 handle;
+ __u32 name;
+ };
+
+You have to put your handle into the *handle* field. After completion, the
+kernel has put the new unique name into the name field. You can now pass
+this name to other processes which can then import the name with the
+``DRM_IOCTL_GEM_OPEN`` ioctl. It takes as argument a structure of type
+``struct drm_gem_open``:
+
+::
+
+ struct drm_gem_open {
+ __u32 name;
+
+ __u32 handle;
+ __u32 size;
+ };
+
+You have to fill in the *name* field with the name of the GEM-object that you
+want to open. The kernel will fill in the *handle* and *size* fields with the
+new handle and size of the GEM-object. You can now access the GEM-object via
+the handle as if you created it with the GEM API.
+
+Besides generic buffer management, the GEM API does not provide any generic
+access. Each driver implements its own functionality on top of this API. This
+includes execution-buffers, GTT management, context creation, CPU access, GPU
+I/O and more. The next higher-level API is *OpenGL*. So if you want to use more
+GPU features, you should use the *mesa3D* library to create OpenGL contexts on
+DRM devices. This does *not* require any windowing-system like X11, but can
+also be done on raw DRM devices. However, this is beyond the scope of this
+man-page. You may have a look at other mesa3D man pages, including libgbm and
+libEGL. 2D software-rendering (rendering with the CPU) can be achieved with the
+dumb-buffer-API in a driver-independent fashion, however, for
+hardware-accelerated 2D or 3D rendering you must use OpenGL. Any other API that
+tries to abstract the driver-internals to access GEM-execution-buffers and
+other GPU internals, would simply reinvent OpenGL so it is not provided. But if
+you need more detailed information for a specific driver, you may have a look
+into the driver-manpages, including **drm-intel**\ (7), **drm-radeon**\ (7) and
+**drm-nouveau**\ (7). However, the **drm-prime**\ (7) infrastructure and the
+generic GEM API as described here allow display-managers to handle
+graphics-buffers and render-clients without any deeper knowledge of the GPU
+that is used. Moreover, it allows to move objects between GPUs and implement
+complex display-servers that don't do any rendering on their own. See its
+man-page for more information.
+
+Examples
+========
+
+This section includes examples for basic memory-management tasks.
+
+Dumb-Buffers
+------------
+
+This examples shows how to create a dumb-buffer via the generic DRM API.
+This is driver-independent (as long as the driver supports dumb-buffers)
+and provides memory-mapped buffers that can be used for scanout. This
+example creates a full-HD 1920x1080 buffer with 32 bits-per-pixel and a
+color-depth of 24 bits. The buffer is then bound to a framebuffer which
+can be used for scanout with the KMS API (see **drm-kms**\ (7)).
+
+::
+
+ struct drm_mode_create_dumb creq;
+ struct drm_mode_destroy_dumb dreq;
+ struct drm_mode_map_dumb mreq;
+ uint32_t fb;
+ int ret;
+ void *map;
+
+ /* create dumb buffer */
+ memset(&creq, 0, sizeof(creq));
+ creq.width = 1920;
+ creq.height = 1080;
+ creq.bpp = 32;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
+ if (ret < 0) {
+ /* buffer creation failed; see "errno" for more error codes */
+ ...
+ }
+ /* creq.pitch, creq.handle and creq.size are filled by this ioctl with
+ * the requested values and can be used now. */
+
+ /* create framebuffer object for the dumb-buffer */
+ ret = drmModeAddFB(fd, 1920, 1080, 24, 32, creq.pitch, creq.handle, &fb);
+ if (ret) {
+ /* frame buffer creation failed; see "errno" */
+ ...
+ }
+ /* the framebuffer "fb" can now used for scanout with KMS */
+
+ /* prepare buffer for memory mapping */
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.handle = creq.handle;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
+ if (ret) {
+ /* DRM buffer preparation failed; see "errno" */
+ ...
+ }
+ /* mreq.offset now contains the new offset that can be used with mmap() */
+
+ /* perform actual memory mapping */
+ map = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset);
+ if (map == MAP_FAILED) {
+ /* memory-mapping failed; see "errno" */
+ ...
+ }
+
+ /* clear the framebuffer to 0 */
+ memset(map, 0, creq.size);
+
+Reporting Bugs
+==============
+
+Bugs in this manual should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues
+
+See Also
+========
+
+**drm**\ (7), **drm-kms**\ (7), **drm-prime**\ (7), **drmAvailable**\ (3),
+**drmOpen**\ (3), **drm-intel**\ (7), **drm-radeon**\ (7), **drm-nouveau**\ (7)
diff --git a/man/drm.7.rst b/man/drm.7.rst
new file mode 100644
index 0000000..df2c1c7
--- /dev/null
+++ b/man/drm.7.rst
@@ -0,0 +1,91 @@
+===
+drm
+===
+
+------------------------
+Direct Rendering Manager
+------------------------
+
+:Date: September 2012
+:Manual section: 7
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+Description
+===========
+
+The *Direct Rendering Manager* (DRM) is a framework to manage *Graphics
+Processing Units* (GPUs). It is designed to support the needs of complex
+graphics devices, usually containing programmable pipelines well suited
+to 3D graphics acceleration. Furthermore, it is responsible for memory
+management, interrupt handling and DMA to provide a uniform interface to
+applications.
+
+In earlier days, the kernel framework was solely used to provide raw
+hardware access to privileged user-space processes which implement all
+the hardware abstraction layers. But more and more tasks were moved into
+the kernel. All these interfaces are based on **ioctl**\ (2) commands on
+the DRM character device. The *libdrm* library provides wrappers for these
+system-calls and many helpers to simplify the API.
+
+When a GPU is detected, the DRM system loads a driver for the detected
+hardware type. Each connected GPU is then presented to user-space via a
+character-device that is usually available as ``/dev/dri/card0`` and can
+be accessed with **open**\ (2) and **close**\ (2). However, it still
+depends on the graphics driver which interfaces are available on these
+devices. If an interface is not available, the syscalls will fail with
+``EINVAL``.
+
+Authentication
+--------------
+
+All DRM devices provide authentication mechanisms. Only a DRM master is
+allowed to perform mode-setting or modify core state and only one user
+can be DRM master at a time. See **drmSetMaster**\ (3) for information
+on how to become DRM master and what the limitations are. Other DRM users
+can be authenticated to the DRM-Master via **drmAuthMagic**\ (3) so they
+can perform buffer allocations and rendering.
+
+Mode-Setting
+------------
+
+Managing connected monitors and displays and changing the current modes
+is called *Mode-Setting*. This is restricted to the current DRM master.
+Historically, this was implemented in user-space, but new DRM drivers
+implement a kernel interface to perform mode-setting called *Kernel Mode
+Setting* (KMS). If your hardware-driver supports it, you can use the KMS
+API provided by DRM. This includes allocating framebuffers, selecting
+modes and managing CRTCs and encoders. See **drm-kms**\ (7) for more.
+
+Memory Management
+-----------------
+
+The most sophisticated tasks for GPUs today is managing memory objects.
+Textures, framebuffers, command-buffers and all other kinds of commands
+for the GPU have to be stored in memory. The DRM driver takes care of
+managing all memory objects, flushing caches, synchronizing access and
+providing CPU access to GPU memory. All memory management is hardware
+driver dependent. However, two generic frameworks are available that are
+used by most DRM drivers. These are the *Translation Table Manager*
+(TTM) and the *Graphics Execution Manager* (GEM). They provide generic
+APIs to create, destroy and access buffers from user-space. However,
+there are still many differences between the drivers so driver-dependent
+code is still needed. Many helpers are provided in *libgbm* (Graphics
+Buffer Manager) from the *Mesa* project. For more information on DRM
+memory management, see **drm-memory**\ (7).
+
+Reporting Bugs
+==============
+
+Bugs in this manual should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues.
+
+See Also
+========
+
+**drm-kms**\ (7), **drm-memory**\ (7), **drmSetMaster**\ (3),
+**drmAuthMagic**\ (3), **drmAvailable**\ (3), **drmOpen**\ (3)
diff --git a/man/drmAvailable.3.rst b/man/drmAvailable.3.rst
new file mode 100644
index 0000000..5da77be
--- /dev/null
+++ b/man/drmAvailable.3.rst
@@ -0,0 +1,41 @@
+============
+drmAvailable
+============
+
+-----------------------------------------------------
+determine whether a DRM kernel driver has been loaded
+-----------------------------------------------------
+
+:Date: September 2012
+:Manual section: 3
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+``int drmAvailable(void);``
+
+Description
+===========
+
+``drmAvailable`` allows the caller to determine whether a kernel DRM
+driver is loaded.
+
+Return Value
+============
+
+``drmAvailable`` returns 1 if a DRM driver is currently loaded.
+Otherwise 0 is returned.
+
+Reporting Bugs
+==============
+
+Bugs in this function should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues
+
+See Also
+========
+
+**drm**\ (7), **drmOpen**\ (3)
diff --git a/man/drmHandleEvent.3.rst b/man/drmHandleEvent.3.rst
new file mode 100644
index 0000000..ecc63ed
--- /dev/null
+++ b/man/drmHandleEvent.3.rst
@@ -0,0 +1,62 @@
+==============
+drmHandleEvent
+==============
+
+-----------------------------------
+read and process pending DRM events
+-----------------------------------
+
+:Date: September 2012
+:Manual section: 3
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+``int drmHandleEvent(int fd, drmEventContextPtr evctx);``
+
+Description
+===========
+
+``drmHandleEvent`` processes outstanding DRM events on the DRM
+file-descriptor passed as ``fd``. This function should be called after
+the DRM file-descriptor has polled readable; it will read the events and
+use the passed-in ``evctx`` structure to call function pointers with the
+parameters noted below:
+
+::
+
+ typedef struct _drmEventContext {
+ int version;
+ void (*vblank_handler) (int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data)
+ void (*page_flip_handler) (int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data)
+ } drmEventContext, *drmEventContextPtr;
+
+Return Value
+============
+
+``drmHandleEvent`` returns 0 on success, or if there is no data to
+read from the file-descriptor. Returns -1 if the read on the
+file-descriptor fails or returns less than a full event record.
+
+Reporting Bugs
+==============
+
+Bugs in this function should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues
+
+See Also
+========
+
+**drm**\ (7), **drm-kms**\ (7), **drmModePageFlip**\ (3),
+**drmWaitVBlank**\ (3)
diff --git a/man/drmModeGetResources.3.rst b/man/drmModeGetResources.3.rst
new file mode 100644
index 0000000..d1358d2
--- /dev/null
+++ b/man/drmModeGetResources.3.rst
@@ -0,0 +1,92 @@
+===================
+drmModeGetResources
+===================
+
+--------------------------------------------------
+retrieve current display configuration information
+--------------------------------------------------
+
+:Date: September 2012
+:Manual section: 3
+:Manual group: Direct Rendering Manager
+
+Synopsis
+========
+
+``#include <xf86drm.h>``
+
+``#include <xf86drmMode.h>``
+
+``drmModeResPtr drmModeGetResources(int fd);``
+
+Description
+===========
+
+``drmModeGetResources`` allocates, populates, and returns a drmModeRes
+structure containing information about the current display
+configuration. The structure contains the following fields:
+
+::
+
+ typedef struct _drmModeRes {
+ int count_fbs;
+ uint32_t *fbs;
+
+ int count_crtcs;
+ uint32_t *crtcs;
+
+ int count_connectors;
+ uint32_t *connectors;
+
+ int count_encoders;
+ uint32_t *encoders;
+
+ uint32_t min_width, max_width;
+ uint32_t min_height, max_height;
+ } drmModeRes, *drmModeResPtr;
+
+The *count_fbs* and *fbs* fields indicate the number of currently allocated
+framebuffer objects (i.e., objects that can be attached to a given CRTC
+or sprite for display).
+
+The *count_crtcs* and *crtcs* fields list the available CRTCs in the
+configuration. A CRTC is simply an object that can scan out a
+framebuffer to a display sink, and contains mode timing and relative
+position information. CRTCs drive encoders, which are responsible for
+converting the pixel stream into a specific display protocol (e.g., MIPI
+or HDMI).
+
+The *count_connectors* and *connectors* fields list the available physical
+connectors on the system. Note that some of these may not be exposed
+from the chassis (e.g., LVDS or eDP). Connectors are attached to
+encoders and contain information about the attached display sink (e.g.,
+width and height in mm, subpixel ordering, and various other
+properties).
+
+The *count_encoders* and *encoders* fields list the available encoders on
+the device. Each encoder may be associated with a CRTC, and may be used
+to drive a particular encoder.
+
+The *min_\** and *max_\** fields indicate the maximum size of a framebuffer
+for this device (i.e., the scanout size limit).
+
+Return Value
+============
+
+``drmModeGetResources`` returns a drmModeRes structure pointer on
+success, NULL on failure. The returned structure must be freed with
+**drmModeFreeResources**\ (3).
+
+Reporting Bugs
+==============
+
+Bugs in this function should be reported to
+https://gitlab.freedesktop.org/mesa/drm/-/issues
+
+See Also
+========
+
+**drm**\ (7), **drm-kms**\ (7), **drmModeGetFB**\ (3), **drmModeAddFB**\ (3),
+**drmModeAddFB2**\ (3), **drmModeRmFB**\ (3), **drmModeDirtyFB**\ (3),
+**drmModeGetCrtc**\ (3), **drmModeSetCrtc** (3), **drmModeGetEncoder** (3),
+**drmModeGetConnector**\ (3)
diff --git a/man/meson.build b/man/meson.build
new file mode 100644
index 0000000..92a4c37
--- /dev/null
+++ b/man/meson.build
@@ -0,0 +1,40 @@
+# Copyright © 2017-2018 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+rst_pages = [
+ ['drm', '7'],
+ ['drm-kms', '7'],
+ ['drm-memory', '7'],
+ ['drmAvailable', '3'],
+ ['drmHandleEvent', '3'],
+ ['drmModeGetResources', '3'],
+]
+foreach page : rst_pages
+ name = page[0] + '.' + page[1]
+ rst = files(name + '.rst')
+ custom_target(
+ name,
+ input : rst,
+ output : name,
+ command : [prog_rst2man, '@INPUT@', '@OUTPUT@'],
+ install : true,
+ install_dir : join_paths(get_option('mandir'), 'man' + page[1]),
+ )
+endforeach